属性 传递给 Invoke-Command 将类型从 IDictionary 更改为 HashTable
Property passed to Invoke-Command changes type from IDictionary to HashTable
我收到一个错误 运行 Invoke-Command
其中脚本块采用字典类型的参数:
Cannot process argument transformation on parameter 'dictionary'.
Cannot convert the "System.Collections.Hashtable" value of type
"System.Collections.Hashtable" to type
"System.Collections.Generic.IDictionary`2[System.String,System.String]".
At line:7 char:1
+ Invoke-Command -ComputerName . -ArgumentList $dictionary -ScriptBlock ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [], ParameterBindin...mationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError
+ PSComputerName : localhost
经过大量挖掘,我能够将脚本缩减为下面的 MVP 以显示此问题的根源:
[System.Collections.Generic.IDictionary[string, string]]$dictionary = New-Object -TypeName 'System.Collections.Generic.Dictionary[string, string]'
$dictionary.Add('one', 'hello')
$dictionary.Add('two', 'world')
Write-Verbose "Main Script $($dictionary.GetType().FullName)" -Verbose #outputs: VERBOSE: Before System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
Invoke-Command -ComputerName . -ArgumentList $dictionary -ScriptBlock {
Param (
#[System.Collections.Generic.IDictionary[string, string]] #if I leave this in I get a conversion error
$dictionary
)
Write-Verbose "Function before $($dictionary.GetType().FullName)" -Verbose #outputs: VERBOSE: After System.Collections.Hashtable
function Poc {} #this line seems to cause the `$dictionary` to become a HashTable
Write-Verbose "Function after $($dictionary.GetType().FullName)" -Verbose #outputs: VERBOSE: After System.Collections.Hashtable
}
似乎如果 Invoke-Command
的脚本块包含任何内联函数,那么参数会自动转换为 HashTable
;而如果脚本块不包含任何嵌套函数定义,则参数将保留为 System.Collections.Generic.IDictionary[string, string]
.
我是否在滥用此功能/是否有通用的解决方法?或者这只是 PowerShell 中的一个错误?
这是一个 PowerShell 远程处理中涉及的反序列化代码的已知问题(这是 Invoke-Command -ComputerName
所基于的),不幸的是,从 PowerShell Core 开始7.0.0-preview.2:
在反序列化时,任何实现 IDictionary
接口的对象都被错误地假定为 总是 是一个常规的非泛型 [hashtable]
[1] 并反序列化。
当原始对象是一个有序字典[2]时,这尤其有问题,因为键的顺序丢失了,索引到它们的能力也是如此。
请参阅 GitHub issue #2861,它被标记为“up for grabs”,这意味着社区可以免费提供解决问题的 PR。
[1] System.Collections.Hashtable
,可在 PowerShell 中使用 @{ ... }
文字创建,其中键和值均为 [object]
类型。
[2] 例如,System.Collections.Specialized.OrderedDictionary
, creatable in PowerShell with [ordered] @{ ... }
literals, also with [object]
-typed keys and values (non-generic); suprisingly, as of this writing, there is no generic ordered dictionary type - see this question.
我收到一个错误 运行 Invoke-Command
其中脚本块采用字典类型的参数:
Cannot process argument transformation on parameter 'dictionary'. Cannot convert the "System.Collections.Hashtable" value of type "System.Collections.Hashtable" to type "System.Collections.Generic.IDictionary`2[System.String,System.String]". At line:7 char:1 + Invoke-Command -ComputerName . -ArgumentList $dictionary -ScriptBlock ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [], ParameterBindin...mationException + FullyQualifiedErrorId : ParameterArgumentTransformationError + PSComputerName : localhost
经过大量挖掘,我能够将脚本缩减为下面的 MVP 以显示此问题的根源:
[System.Collections.Generic.IDictionary[string, string]]$dictionary = New-Object -TypeName 'System.Collections.Generic.Dictionary[string, string]'
$dictionary.Add('one', 'hello')
$dictionary.Add('two', 'world')
Write-Verbose "Main Script $($dictionary.GetType().FullName)" -Verbose #outputs: VERBOSE: Before System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
Invoke-Command -ComputerName . -ArgumentList $dictionary -ScriptBlock {
Param (
#[System.Collections.Generic.IDictionary[string, string]] #if I leave this in I get a conversion error
$dictionary
)
Write-Verbose "Function before $($dictionary.GetType().FullName)" -Verbose #outputs: VERBOSE: After System.Collections.Hashtable
function Poc {} #this line seems to cause the `$dictionary` to become a HashTable
Write-Verbose "Function after $($dictionary.GetType().FullName)" -Verbose #outputs: VERBOSE: After System.Collections.Hashtable
}
似乎如果 Invoke-Command
的脚本块包含任何内联函数,那么参数会自动转换为 HashTable
;而如果脚本块不包含任何嵌套函数定义,则参数将保留为 System.Collections.Generic.IDictionary[string, string]
.
我是否在滥用此功能/是否有通用的解决方法?或者这只是 PowerShell 中的一个错误?
这是一个 PowerShell 远程处理中涉及的反序列化代码的已知问题(这是 Invoke-Command -ComputerName
所基于的),不幸的是,从 PowerShell Core 开始7.0.0-preview.2:
在反序列化时,任何实现 IDictionary
接口的对象都被错误地假定为 总是 是一个常规的非泛型 [hashtable]
[1] 并反序列化。
当原始对象是一个有序字典[2]时,这尤其有问题,因为键的顺序丢失了,索引到它们的能力也是如此。
请参阅 GitHub issue #2861,它被标记为“up for grabs”,这意味着社区可以免费提供解决问题的 PR。
[1] System.Collections.Hashtable
,可在 PowerShell 中使用 @{ ... }
文字创建,其中键和值均为 [object]
类型。
[2] 例如,System.Collections.Specialized.OrderedDictionary
, creatable in PowerShell with [ordered] @{ ... }
literals, also with [object]
-typed keys and values (non-generic); suprisingly, as of this writing, there is no generic ordered dictionary type - see this question.