1

所以我正在使用那种有问题的 Sapien powershell studio 来制作一个 powershell 驱动的 GUI 应用程序,并且我正在尝试执行 ADSI 查询。

$nameOfDeviceInput 是一个 System.Windows.Forms.TextBox

在一种形式上,我具有以下功能:

$buttonPerformAction_Click={
    if (FindInAD($nameOfDeviceInput.Text).Count -gt 0)
    {
        $buttonPerformAction.BackColor = 'Red'
        $buttonPerformAction.Text = "System already exists in AD with that name. Try another name"
        return
    }
.....
}

在“主”表单上,我有 FindInAD 函数

function FindInAd($nameOfSystem)
{
    Write-Host "seeking system" $nameOfSystem
    ([adsisearcher]"(CN=$nameOfSystem)").FindAll()
}

FindInAd() 失败,因为无论出于何种原因,$nameOfSystem 设置为 1,如果我没有将其显式转换为字符串,它会隐式转换为 Int32(显然)

我尝试了以下方法:

通过标注它所属的表单来完全限定文本框输入( $adObjectModifier )

 $buttonPerformAction_Click={
        if (FindInAD($adObjectModifier.$nameOfDeviceInput.Text).Count -gt 0)
        {
            $buttonPerformAction.BackColor = 'Red'
            $buttonPerformAction.Text = "System already exists in AD with that name. Try another name"
            return
        }
    .....
    }

将 $nameOfSystem 参数显式转换为 [string] 类型

function FindInAd([string]$nameOfSystem)
{
    Write-Host "seeking system" $nameOfSystem
    ([adsisearcher]"(CN=$nameOfSystem)").FindAll()
}

将原始字符串从 AdObjectModifier 表单传递到 FindInAD。

.... 

if (FindInAD("Test").Count -gt 0)

....

当时输出管道上没有其他东西,(至少不是来自我)在方法调用之间。它是 EventHandler > 带有字符串参数的函数调用

为什么我传递的字符串变成了数字???

编辑:我认为我传递的参数正在以某种方式自动替换为结果布尔值,但这对我来说没有任何意义......

4

1 回答 1

2

您有语法问题

FindInAD($nameOfDeviceInput.Text).Count # WRONG

注意:在此上下文中的错误意味着:语法形式上是有效的,但没有达到您的预期- 请参阅底部部分。

它应该是:

(FindInAD $nameOfDeviceInput.Text).Count

PowerShell命令- 函数、cmdlet、脚本和外部程序 -像 shell 命令一样被调用-foo arg1 arg2不是C# 方法 - foo('arg1', 'arg2')

那是:

  • 不要参数列表 放在(...)周围

    • 但是,如果您希望命令调用参与表达式,则确实需要(...) 将调用作为一个整体,如上所示,可以访问属性.Count- 请参阅此答案以获取更多信息。
  • 用空格分隔参数(至少一个空格),彼此和命令名称 -不要使用,

    • ,参数之间的功能不同:它构造一个作为单个参数传递的数组- 见下文。
  • 您可以将简单的字符串(既不包含空格也不包含 PowerShell 元字符,例如;or的字符串&)作为裸词传递;也就是说,引用它们是可选的;例如,foo 'bar'您可以调用而不是调用foo bar- 请参阅此答案以了解 PowerShell 如何解析未引用的命令参数。

  • 此外,如果目标函数或脚本已显式声明参数二进制cmdlet 总是这样做),例如-barand -baz,您可以将值作为命名参数传递,即通过在它们前面加上目标参数名称;这样做是脚本中的好习惯:foo -bar arg1 -baz arg2

相比之下,调用对象方法使用与常规编程语言如 C# ( )相似的语法$obj.foo('arg1', 'arg2')

这种差异与两种PowerShell 的两种基本解析模式有关,在此答案中进行了详细说明:

  • 命令参数模式解析- 就像在 shell 中一样。

  • 方法调用和基于运算符的表达式以表达式模式解析- 就像在常规编程语言中一样。

为了让 PowerShell 发挥双重作用,需要这些模式:一方面作为shell ,另一方面作为脚本(编程)语言


PowerShell 可以帮助您避免这种语法问题

请注意,问题不在于使用方法语法调用命令无效的语法,而是它不能按预期工作,这可能难以诊断。

简而言之:当您调用command foo asfoo('foo', 'bar')时,('foo', 'bar')是一个2 元素数组,然后将其foo 作为单个参数传递给。

为了防止问题开始,您可以设置Set-StrictMode-Version 2或更高,如果您在调用命令时不小心使用了方法语法,则 PowerShell 会报告错误:

# Turn on the check for accidental method syntax.
# Note: This also turns on ADDITIONAL checks - see below.
Set-StrictMode -Version 2

# This call now produces an ERROR, because the proper syntax would be:
#    foo 'a' 'b'
foo('a', 'b')

注意事项

  • Set-StrictMode -Version 2包括额外的严格性检查,您还必须遵守这些检查,特别是:

    • 不得引用不存在的变量
    • 你不能引用不存在的属性;有关 PowerShell 统一处理标量和集合的相关缺陷,请参阅GitHub 问题 #2798 。
  • 只有带有多个参数(例如, )的伪方法调用才会报告错误
    foo('bar', 'baz'),而不是只有一个;例如,foo('bar')被接受,因为单参数情况通常仍然(意外地)有效。

  • 违反严格性报告的错误是语句终止错误:也就是说,它们只终止手头的语句,但默认情况下脚本继续;为了确保整体执行中止 - 在任何类型的错误中 - 您必须
    $ErrorActionPreference = 'Stop'在代码的开头进行设置。有关更多信息,请参阅此答案


至于你尝试了什么:

FindInAD($nameOfDeviceInput.Text).Count

是相同的:

FindInAD ($nameOfDeviceInput.Text).Count

也就是说,表达式 ($nameOfDeviceInput.Text).Count的结果作为参数传递给函数FindInAD

于 2020-12-08T23:46:28.060 回答