循环寄存器ArgumentCompleter生成不正确的参数补全



我有一个模块,它有一个动态派生枚举值的哈希表,我认为将其合并到Register ArgumentCompleter中以完成选项卡会很巧妙。

这里的动机是,我不能直接设置模块函数的输入参数来自动转换为枚举类型(这将正确地启用制表符完成(,因为我希望动态派生枚举,以避免用户手动管理枚举值,以及由于枚举的.NET实现的限制——我需要允许使用带破折号或以数字开头的字符串,以及可能的null值,遗憾的是,枚举不允许所有这些字符串。我的想法是通过Register ArgumentCompleter添加制表符完成的参数值来解决问题。

问题:我将此解决方法构建为加载在模块清单的ScriptsToProcess成员的第一个位置的脚本,因此,当我循环遍历哈希表键并运行Register ArgumentCompleter时,我发现设置了不正确的值。

要复制的示例代码:

function test {param($a, $b, $c, $d )}
$ht = @{
'1' = @('a', @('a1','a2'))
'2' = @('b', @('b1','b2'))
'3' = @('c', @('c1','c2'))
'4' = @('d', @('d1','d2'))
}
Foreach ($enum in $ht.Keys){
$paramName = $ht.$enum[0]
$paramValue = $ht.$enum[1]
write-host $paramName
write-host $paramValue
Register-ArgumentCompleter -CommandName test2 -ParameterName $paramName -ScriptBlock {$paramValue}
}
PS> test -a <tab>
b1 b2

这是PS 7.2.5。在Windows PowerShell 5.1.19041中,我将c1c2作为建议值。您可以从主机写入中看到,这取决于ht循环中最后解析的键。

我还尝试过$ht.["$enum"][0|1]将键类型显式转换为字符串,但没有成功。当我在循环中编写host时,所有的值似乎都是正确的。

这看起来像是我的错误还是bug?

循环完成时,$enum将具有排序顺序中最后一个键的值。

使用ScriptBlock.GetNewClosure()在调用GetNewClosure()时关闭$ht$enum的值,使脚本块保留$ht$enum:的原始值


function test {param($a, $b, $c, $d )}
$ht = @{
'1' = @('a', @('a1','a2'))
'2' = @('b', @('b1','b2'))
'3' = @('c', @('c1','c2'))
'4' = @('d', @('d1','d2'))
}
Foreach ($enum in $ht.Keys){
Register-ArgumentCompleter -CommandName test -ParameterName $ht.$enum[0] -ScriptBlock { $ht.$enum[1] }.GetNewClosure()
}

FWIW您可以显著简化$ht表格:

$ht = @{
'a' = @('a1','a2')
'b' = @('b1','b2')
'c' = @('c1','c2')
'd' = @('d1','d2')
}
Foreach ($enum in $ht.Keys){
Register-ArgumentCompleter -CommandName test -ParameterName $enum -ScriptBlock { $ht[$enum] }.GetNewClosure()
}

最新更新