Joh*_*van 6 powershell dictionary hashtable psobject powershell-v5.1
Invoke-Command
我在脚本块采用字典类型参数的地方运行时遇到错误:
无法处理参数“字典”的参数转换。无法将“System.Collections.Hashtable”类型的“System.Collections.Hashtable”值转换为“System.Collections.Generic.IDictionary`2[System.String,System.String]”类型。在行:7 字符:1 + Invoke-Command -ComputerName 。-ArgumentList $dictionary -ScriptBlock ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [], ParameterBindin...mationException + FullQualifiedErrorId : ParameterArgumentTransformationError + PS计算机名称:本地主机
经过大量挖掘后,我能够将脚本简化为下面的 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
}
Run Code Online (Sandbox Code Playgroud)
似乎如果 的 脚本块Invoke-Command
包含任何内联函数,则参数会自动转换为HashTable
; 而如果脚本块不包含任何嵌套函数定义,则参数将保留为System.Collections.Generic.IDictionary[string, string]
.
我是否滥用了此功能/是否有常见的解决方法?或者这只是 PowerShell 中的一个错误?
您会看到 基于 XML 的序列化基础架构的设计限制,该基础架构是 PowerShell远程处理的基础(这是其Invoke-Command -ComputerName
基础):
实现该接口的类型的对象仅IDictionary
被反序列化为两种非泛型类型之一(即使原始的完整类型名称记录在序列化数据中),即:
仅在PowerShell 7.3.0 及更高版本中(见下文),当且仅当使用该精确类型作为输入时,才会使用[ordered]
哈希表 ( System.Collections.Specialized.OrderedDictionary
) 。 [2]
[hashtable]
( System.Collections.Hashtable
)对于所有其他字典类型,包括通用类型,例如[System.Collections.Generic.IDictionary[string, string]]
您的情况;这种类型的键和值都是[object]
类型化的。
这种潜在的类型保真度损失是 PowerShell 远程处理所固有的,因为只有有限的一组众所周知的类型会被忠实地反序列化,因为我们的想法是使远程处理能够跨不同的 PowerShell 版本以及现在在两个 PowerShell版本之间工作。有关 PowerShell 序列化的系统概述,请参阅此答案。
然而,对于字典类型的基本用法,类型保真度的损失并不重要:由于IDictionary
接口、枚举、条目访问和获取条目计数的工作方式都是相同的。
但是,在PowerShell 7.2.x 及更低版本(包括Windows PowerShell)中,[ordered]
哈希表被错误地反序列化为无序 [hashtable]
s,这明显丢失了其条目的原始顺序,并阻止通过反序列化对象上的位置索引进行条目访问。
请参阅GitHub 问题 #2861了解原始错误报告。
如前所述,此问题已在 v7.3.0 中修复(请参阅GitHub PR #15545)。
归档时间: |
|
查看次数: |
583 次 |
最近记录: |