Вопрос

Powershell Version: 3.0

Hello fellow scripters. I have an issue that I can't seem to find an answer to.

Summary: When attempting to begin a job, the scriptblock parameters are removing the cast of [System.Collections.Specialized.OrderedDictionary] and replacing it with [Hashtable] (that is if I don't cast the parameter of the scriptblock). An example of my scenario is below:

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

When attempting to pass an OrderedDictionary object into the job with key/value pairs in it, it acts like it's passing an object with more properties than it was expecting for that object type:

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

I'm using the following line to execute my job:

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

RESULT:

ERROR: Cannot process argument transformation on parameter 'Params'. Cannot create object of type "System.Collections.Specialized.OrderedDictionary". The Param1 property was not found for the System.Collections.Specialized.OrderedDictionary object. The available property is: [Count ] , [IsReadOnly ] , [Keys ] , [Values ] , [IsFixedSize ] , [SyncRoot ] , [IsSynchronized ]

NOTE: When passing no key/value pairs, the cast remains and object passes into the scriptblock just fine (with cast in parameter list).

Can anyone detail the exact cause or what the Start-Job cmdlet is doing? Am I just using the job wrong? Is this object type just not usable in jobs? Is it because it's a system object?

Нет правильного решения

Другие советы

The use of the script block within your Start-Job seems, well, odd to me. I'm not sure why you're doing in that way, but with the example you gave it sure looks like there should be a better way to do it.
I don't think your issue is with the job so much as with your construction of the OrderedDictionary. Take the job out of it and try and just make that object the way you are now and it throws errors.

At the very least you need to insert an @ symbol after [Ordered].

Since you seem to be requiring some parameters and all, if it were me I'd move it into a function and then call the function from the $ret = line like this:

$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

This parses without errors on my end, though I didn't actually pass real job data to it and it just basically did nothing. Obviously you will need to modify it for your needs if nothing else change the stupid function name I randomly came up with.

The problem appears to be the result of casting a [hashtable] to a [System.Collections.Specialized.OrderedDictionary].

This code exhibits similar behavior:

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

I can only surmise that within the Start-Job cmdlet, your [OrderedDictionary] is cast back to a [hashtable] before it is passed to your scriptblock.

Will an unordered dictionary work for you? Using the [IDictionary] interface works:

$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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top