1

Powershell 版本:3.0

各位编剧你好。我有一个问题,我似乎无法找到答案。

摘要:尝试开始工作时,脚本块参数正在删除 [System.Collections.Specialized.OrderedDictionary] 的演员表并将其替换为 [Hashtable] (也就是说,如果我不转换脚本块的参数)。我的场景示例如下:

$Job = Start-Job -ScriptBlock {
 param(
    [System.Collections.Specialized.OrderedDictionary]$Params = $(throw "Please pass Params.")
 )
} -Name "Execute" -ErrorVariable Errors -ErrorAction Stop -ArgumentList $Params

当尝试将 OrderedDictionary 对象传递给其中包含键/值对的作业时,它就像传递一个具有比该对象类型预期的更多属性的对象:

$Params = [ordered]@{ "Param1" = "Value1"; "Param2" = "Value2" }

我正在使用以下行来执行我的工作:

$ret = Receive-Job $job -Wait -AutoRemoveJob

结果:

错误:无法处理参数“Params”的参数转换。无法创建“System.Collections.Specialized.OrderedDictionary”类型的对象。找不到 System.Collections.Specialized.OrderedDictionary 对象的 Param1 属性。可用的属性是: [Count ] 、 [IsReadOnly ] 、 [Keys ] 、 [Values ] 、 [IsFixedSize ] 、 [SyncRoot ] 、 [IsSynchronized ]

注意:当不传递键/值对时,强制转换仍然存在,并且对象可以很好地传递到脚本块(在参数列表中使用强制转换)。

谁能详细说明确切的原因或 Start-Job cmdlet 正在做什么?我只是用错了工作吗?这种对象类型不能在工作中使用吗?是因为它是一个系统对象吗?

4

2 回答 2

0

在 Start-Job 中使用脚本块对我来说似乎很奇怪。我不确定您为什么要这样做,但是您给出的示例肯定看起来应该有更好的方法来做到这一点。
我认为您的问题不在于工作,而在于您构建 OrderedDictionary。把工作从它身上拿出来,试着把那个对象变成你现在的样子,它会抛出错误。

至少您需要在 .@之后插入一个符号[Ordered]

由于您似乎需要一些参数和所有参数,如果是我,我会将其移动到一个函数中,然后从该$ret =行调用该函数,如下所示:

$Params = [ordered]@{ "Param1" = "Value1"; "Param2" = "Value2" }
Function Quibble {
 param(
    [System.Collections.Specialized.OrderedDictionary]$ParamIn = $(throw "Please pass Params.")
 )
 Start-Job -ScriptBlock {$ParamIn} -Name "Execute" -ErrorVariable Errors -ErrorAction Stop -ArgumentList $ParamIn
}
$ret = Receive-Job $(Quibble $Params) -Wait -AutoRemoveJob

尽管我实际上并没有将真实的工作数据传递给它,而且它基本上什么也没做,但它最终解析没有错误。显然,如果没有其他方法更改我随机想出的愚蠢函数名称,您将需要根据需要对其进行修改。

于 2014-03-04T00:31:12.387 回答
0

问题似乎是将 [hashtable] 转换为 [System.Collections.Specialized.OrderedDictionary] 的结果。

此代码表现出类似的行为:

$hashTable = @{ "Param1" = "Value1"; "Param2" = "Value2" }
[System.Collections.Specialized.OrderedDictionary]$dictionary = $hashTable

我只能推测在 Start-Job cmdlet 中,您的 [OrderedDictionary] 在传递给您的脚本块之前会被转换回 [hashtable]。

无序字典对你有用吗?使用 [IDictionary] 接口可以:

$Dictionary = [ordered]@{ "Param1" = "Value1"; "Param2" = "Value2" }

$job = Start-Job -Name "Execute" -ArgumentList $Dictionary -ScriptBlock {
    param
    (
        <#
        Using this interface type gives the following error:
            Cannot process argument transformation on parameter 'Params'.
            Cannot convert the "System.Collections.Hashtable" value of type "System.Collections.Hashtable" to type "System.Collections.Specialized.IOrderedDictionary".

        This would indicate that Start-Job is likely casting the [OrderedDictionary] back to a [hashtable].

        [System.Collections.Specialized.IOrderedDictionary]
        $Params = $(throw "Please pass Params.")
        #>

        # This type works but is unordered.
        [System.Collections.IDictionary]
        $Params = $(throw "Please pass Params.")
    )

    # Just to prove the params are passed in.
    $Params | Out-String | Write-Host -ForegroundColor Green
}

$ret = Receive-Job $job -Wait -AutoRemoveJob
于 2014-03-04T00:47:25.980 回答