【问题标题】:Property passed to Invoke-Command changes type from IDictionary to HashTable传递给 Invoke-Command 的属性将类型从 IDictionary 更改为 HashTable
【发布时间】:2019-12-25 15:06:27
【问题描述】:

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

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

经过大量挖掘,我能够将脚本简化为下面的 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 中的一个错误?

【问题讨论】:

  • 哇哦。我一直认为这是一个核心的 PS 问题。但从来没有想过一个错误。 mkelement0 巧妙地回答了这个问题,我的建议是永久储存这个问题。提请版主注意冻结此问题。这是可以帮助所有人的核心 PS 缺陷之一。感谢您的努力

标签: powershell dictionary hashtable psobject powershell-v5.1


【解决方案1】:

不幸的是,从 PowerShell Core 7.0.0-preview.2 开始,

这是 PowerShell 远程处理中涉及的反序列化代码的一个已知问题(这是 Invoke-Command -ComputerName 所基于的) :

在反序列化时,任何实现IDictionary 接口的对象都被错误地假定为总是是常规的、非泛型的[hashtable][1]并反序列化。

当原始对象是一个有序字典[2]时,这尤其成问题,因为键的顺序丢失了,索引到它们的能力也丢失了.

参见GitHub issue #2861,它被标记为“up for grabs”,这意味着社区可以免费提供解决问题的 PR。


[1] System.Collections.Hashtable,可在 PowerShell 中使用 @{ ... } 文字创建,其中键和值都是 [object]-typed。

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

【讨论】:

  • 对不起,如果我听起来很菜鸟,但我想澄清一下。非通用哈希表是什么意思?您只是指订单吗?
  • @RanadipDutta:请看我的更新;排序与使用泛型类型的方面是不相关的。 PowerShell 支持的无序 (@{ ... }) 和有序 ([ordered] @{ ... }) 类型都是非泛型的。 (而且,令人惊讶的是,目前没有 generic 有序字典 - 请参阅 stackoverflow.com/q/2629027/45375.
猜你喜欢
  • 2021-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
  • 2011-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多