当condition为true时,ValidateScript意外返回false

时间:2018-03-10 00:11:07

标签: powershell

我有一个PowerShell函数我正在编写代码来构建和执行各种logman.exe命令,所以我不必每次都想引用提供程序GUID并输入命令从不同的来源捕获。其中一个参数是文件名,我正在对参数执行一些验证。最初我使用-match '.+?\.etl$'检查文件名是否具有.etl扩展名,并在路径上另外进行了一些验证。我后来决定删除路径验证,但忽略了将验证属性更改为ValidatePattern

我发现虽然它在我用来编写和验证它的机器上完美运行,但在我的Server 2016 Core机器上,它在调用函数时似乎行为不端但是如果我在提示符下运行相同的检查它按预期工作。

PowerShell:

[Parameter(ParameterSetName="Server", Mandatory=$true)]
[Parameter(ParameterSetName="Client", Mandatory=$true)]
[ValidateScript({$FileName -match '.+?\.etl$'}]
[string] $FileName = $null

输出:

PS C:\Users\Administrator> Start-TBLogging -ServerLogName HTTPSYS -FileName ".\TestLog.etl"
PS C:\Users\Administrator> Start-TBLogging : Cannot validate argument on parameter 'FileName'. The "$FileName -match '.+?\.etl$'" validation script
for the argument with value ".\TestLog.etl" did not return a result of True. Determine why the validation script failed,
and then try the command again.
At line:1 char:50
+ Start-TBLogging -ServerLogName HTTPSYS -FileName ".\TestLog.etl"
+                                                  ~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Start-TBLogging], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Start-TBLogging

手动尝试:

PS C:\Users\Administrator> $FileName = ".\TestLog.etl"
PS C:\Users\Administrator> $FileName -match '.+?\.etl$'
True

更改使用ValidatePattern的功能后,它在任何地方都可以正常工作,但我想知道是否有人可以了解不连续性。

1 个答案:

答案 0 :(得分:2)

正如Joshua Shearer在对问题的评论中指出的那样,必须使用自动变量$_ (或其别名形式,$PSItem), 参数变量引用要在[ValidateScript({ ... })] 内验证的参数。

因此,而不是:

# !! WRONG: The argument at hand has NOT yet been assigned to parameter     
#           variable $FileName; by design, that assignment
#           doesn't happen until AFTER (successful) validation.
[ValidateScript({ $FileName -match '.+?\.etl$' }]
[string] $FileName

使用:

# OK: $_ (or $PSItem) represents the argument to validate inside { ... }
[ValidateScript({ $_ -match '.+?\.etl$' })]
[string] $FileName

正如briantist在该问题的其他评论中指出的那样,脚本块$FileName内部将具有来自来电者范围的值(如果有) (或其祖先范围)。