Start-Job cmdlet删除传递的对象的强制转换

时间:2014-03-03 22:28:43

标签: powershell powershell-v3.0 jobs start-job

Powershell版本:3.0

你好的脚本编写者。我有一个问题似乎无法找到答案。

要点: 尝试开始作业时,scriptblock参数将删除[System.Collections.Specialized.OrderedDictionary]的强制转换并将其替换为[Hashtable](即如果我不转换scriptblock的参数)。我的方案的一个例子如下:

$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]

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

任何人都可以详细说明确切原因或Start-Job cmdlet正在执行的操作吗?我只是错误地使用了这份工作吗?这种对象类型在作业中不可用吗?是因为它是一个系统对象吗?

2 个答案:

答案 0 :(得分: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

虽然我实际上没有将真正的工作数据传递给它,但它基本上没有做任何事情。显然,如果没有其他任何东西改变我随机提出的愚蠢的函数名称,你将需要根据自己的需要对其进行修改。

答案 1 :(得分:0)

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

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

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

我只能推测,在Start-Job cmdlet中,您的[OrderedDictionary]会在传递给您的scriptblock之前被转换回[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