“无法添加属性”消息是(或曾经是)一个 PowerShell 错误,我已将其提交给 Microsoft这个错误报告。这个特定问题似乎已经得到解决(可能在 V5.1 左右)。但任何对 Powershell 闭包感兴趣的人可能仍然会发现下面的信息很有趣。
有一个适用于早期版本的解决方法,但首先这里有一个简化的重现案例,它会产生相同的错误:
function Test-ClosureWithValidation {
[CmdletBinding()]
param(
[Parameter()]
[ValidateSet('Option1','Option2')]
[String[]]$Options
)
[scriptblock] $closure = {"OK"}.GetNewClosure();
$closure.Invoke()
}
Test-ClosureWithValidation -Options Option1
解决方法取决于 GetNewClosure() 通过迭代来工作的事实局部变量在调用脚本的上下文中,将这些局部变量绑定到脚本的上下文中。出现该错误是因为它复制了$Options变量包括验证属性。您可以通过创建仅包含所需局部变量的新上下文来解决该错误。在上面的简单重现中,这是一种单行解决方法:
[scriptblock] $closure = &{ {"OK"}.GetNewClosure();}
上面的行现在创建了一个没有局部变量的作用域。对于您的情况来说,这可能太简单了;如果您需要外部作用域中的一些值,只需将它们复制到新作用域中的局部变量中,例如:
[scriptblock] $closure = &{
$options = $options;
{"OK $options"}.GetNewClosure();
}
请注意,上面的第二行创建了一个新的 $options 变量,并将其分配给value外部变量的属性不会传播。
最后,我不确定在您的示例中为什么您需要调用 GetNewClosure 。变量 $this 不是普通的局部变量,无论您是否创建闭包,它都将在您的脚本属性中可用。例子:
function Test-ScriptPropertyWithoutClosure {
[CmdletBinding()]
param(
[Parameter()]
[ValidateSet('Option1','Option2')]
[String[]]$Options
)
[pscustomobject]@{ Timestamp= Get-Date} |
Add-Member ScriptProperty ExpensiveScriptProperty {
$this | get-member -MemberType Properties| % Name
} -PassThru
}
Test-ScriptPropertyWithoutClosure -Options Option1 | fl