PowerShell函数调用将传递的字符串更改为int

dy1byipe  于 2022-11-10  发布在  Shell
关注(0)|答案(1)|浏览(153)

因此,我使用有缺陷的Sapien PowerShell工作室来制作PowerShell驱动的图形用户界面应用程序,并尝试执行一个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
    }
.....
}

在“Main”表单上,我有函数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参数显式转换为[字符串]的类型

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

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

.... 

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

....

当时输出管道上没有其他东西,(至少不是来自我)在方法调用之间。它是带字符串参数的EventHandler>函数调用
为什么我传递的字符串变成了数字?
编辑:我认为我传递的参数以某种方式被结果布尔值自动替换,但这对我来说没有任何意义……

nzkunb0c

nzkunb0c1#

**您有语法问题

FindInAD($nameOfDeviceInput.Text).Count # WRONG

注:此上下文中的错误意味着:语法在形式上是有效的,但没有达到您的预期--见下一节。
它应该是:

(FindInAD $nameOfDeviceInput.Text).Count

**PowerShell命令-函数、cmdlet、脚本和外部程序-被调用类似于外壳命令-foo arg1 arg2-和*不像C#方法-foo('arg1', 'arg2')

即:

  • 不要(...)放在参数列表中*。
  • 然而,您确实需要围绕整个调用的(...)如果您希望命令调用参与表达式,如上图所示,访问属性.Count-有关详细信息,请参阅this answer
  • 使用空格分隔参数,彼此之间和命令名中都是如此-不要使用,
  • ,参数之间的作用不同:它构造一个数组,该数组作为单个参数传递-见下文。
  • 您可以将简单字符串(既不包含空格也不包含PowerShell元字符的字符串,如;&)作为无引号传递;即,引用它们是可选的;例如,您可以调用foo bar而不是foo bar-有关PowerShell如何解析未引用的命令参数的信息,请参阅this answer
  • 此外,如果目标函数或脚本具有显式声明的参数(二进制cmdlet总是这样做),如-bar-baz,则可以将值作为命名的参数传递,即在它们前面加上目标参数名称;这样做在脚本中是很好的做法:foo -bar arg1 -baz arg2

相比之下,调用对象**的方法使用C#($obj.foo('arg1', 'arg2'))等常规编程语言熟悉的语法
这种差异涉及两个PowerShell's two fundamental parsing modes,在this answer中有详细说明:

**命令是在参数模式下解析的--就像在外壳中一样。
**方法调用
和基于运算符的表达式在表达式模式下进行解析-就像在常规编程语言中一样。

为了让PowerShell具有“双重职责”,这些模式是必需的:一方面作为外壳,另一方面作为脚本(编程)语言

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

请注意,问题不在于使用方法语法调用命令无效语法,而是它不能像预期的那样工作,这可能很难诊断。
简而言之:**当您将
COMMAND*foo调用为foo('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 issue #2798
  • 只有具有多个个参数的伪方法调用才会报告错误(例如,

foo('bar', 'baz')),而不是只有一个;例如,foo('bar')被接受,因为单参数情况通常仍然(意外地)起作用。

  • 报告的违反严格性的错误是STATEMENT-终止错误:即它们只终止手头的语句,但默认情况下脚本继续;要确保在任何类型的错误上整体执行中止-您必须设置

代码开头的$ErrorActionPreference = 'Stop'。有关更多信息,请参见this answer
至于你尝试了什么
FindInAD($nameOfDeviceInput.Text).Count
等同于:
FindInAD ($nameOfDeviceInput.Text).Count
也就是说,表达式($nameOfDeviceInput.Text).Count的结果作为参数传递给函数FindInAD

相关问题