Search code examples
windowspowershellpropertiesjobs

How to get one property and output from a child job?


I have a child job in a file test.ps1:

param($unit)
$p = $unit

Start-Job -Name $unit -ScriptBlock {
    param($p)

    "Hallo $p"
    New-Object PSCustomObject -Property @{
        Not_found = "agurk"
    }
} -ArgumentList $p

When I do:

PS> .\test 2
PS> $a=Get-Job|Receive-Job |Select-Object -Property Not_found

I unfortunately get

PS> $a.count
2

Why 2 and not 1?

And I have to do

PS> $a[1].Not_found
agurk

in order to get the value.

I want to create a child job which produces some output, and one property and only one for the caller to investigate. How can I achieve that?


Solution

  • You're getting a count of 2 because your job returns the string "Hallo 2" and your custom object @{Not_found="agurk"}. From the documentation:

    In Windows PowerShell®, the results of each statement are returned as output, even without a statement that contains the Return keyword.

    The Select-Object doesn't skip over or remove that string, instead it creates a new custom object with an empty property Not_found, so you end up with a result like this:

    [
      { 'Not_found': '' },
      { 'Not_found': 'agurk' }
    ]

    If you don't want the string output to be captured, change this line:

    "Hallo $p"
    

    into this:

    Write-Host "Hallo $p"
    

    Or don't create undesired output in the first place.

    If the additional output is desired and you need to be able to redirect it separately from the returned object you can't use Write-Host, though, since that cmdlet writes directly to the host console (meaning its output cannot be captured or redirected). Instead you need to write to a different stream, e.g. the verbose stream:

    Write-Verbose "Hallo $p"
    

    Note that you need PowerShell v3 or newer to be able to redirect streams other than the Success and Error streams.