传递给Invoke-Command的属性将类型从IDictionary更改为HashTable [英] Property passed to Invoke-Command changes type from IDictionary to HashTable

查看:106
本文介绍了传递给Invoke-Command的属性将类型从IDictionary更改为HashTable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在运行Invoke-Command时遇到错误,其中脚本块采用了dictionary类型的参数:

I've been getting an error running Invoke-Command where the script block takes a parameter of type dictionary:

无法处理参数'dictionary'上的参数转换. 无法转换类型的"System.Collections.Hashtable"值 键入"System.Collections.Hashtable" "System.Collections.Generic.IDictionary`2 [System.String,System.String]". 在第7行:1个字符 +调用命令-ComputerName. -ArgumentList $ dictionary -ScriptBlock ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~ + CategoryInfo:InvalidData:(:) [],ParameterBindin ... mationException + FullyQualifiedErrorId:ParameterArgumentTransformationError + PSComputerName:本地主机

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,以显示此问题的根源:

After a lot of digging I was able to reduce the script to the the MVP below to show the root of this issue:

[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].

It seems that if the script block for Invoke-Command includes any inline functions then the parameter is automatically converted to a HashTable; whilst if the script block doesn't contain any nested function definitions the parameter is left as a System.Collections.Generic.IDictionary[string, string].

我是否滥用此功能/是否有常见的解决方法?还是仅仅是PowerShell中的错误?

Am I misusing this feature / is there a common workaround? Or is this a just a bug in PowerShell?

推荐答案

这是PowerShell远程处理中涉及的反序列化代码的已知问题(这是Invoke-Command -ComputerName所基于的) ,很遗憾,从PowerShell Core 7.0.0-preview.2开始:

This is a known problem with the deserialization code that is involved in PowerShell remoting (which is what Invoke-Command -ComputerName is based on), unfortunately, as of PowerShell Core 7.0.0-preview.2:

反序列化时,错误地将实现IDictionary接口的任何对象假定为始终是常规的,非通用的[hashtable] [1] 并反序列化.

On deserialization, any object that implements the IDictionary interface is incorrectly assumed to always be a regular, non-generic [hashtable][1] and deserialized as such.

当原始对象是 ordered 字典 [2] 时,这尤其成问题,因为会丢失键的顺序以及索引索引的能力

This is especially problematic when the original object was an ordered dictionary[2], because the ordering of the keys is lost, as is the ability to index into them.

请参见此GitHub问题,其标记为向上争夺",这意味着社区可以自由提供解决问题的PR.

See this GitHub issue, which is tagged as "up for grabs", meaning that the community is free to offer a PR that fixes the problem.

[1] System.Collections.Hashtable ,可在PowerShell中使用@{ ... }文字创建,其中键和值均为[object]类型.

[1] System.Collections.Hashtable, creatable in PowerShell with @{ ... } literals, where both the keys and values are [object]-typed.

[2]例如, System.Collections.Specialized.OrderedDictionary ,可以在PowerShell中使用[ordered] @{ ... }文字,也可以使用[object]类型的键和值(非通用)创建;令人惊讶的是,在撰写本文时,还没有 generic 排序的字典类型-请参阅此问题.

[2] E.g., 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的属性将类型从IDictionary更改为HashTable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆