Search code examples
powershellrunspace

runspace: EndInvoke() fails to return all the scriptblocks output , only the last exception


The script block

$sb = {
 write-output "Testing 1"
 write-output "Testing 2"
 throw " Exception in sb"
}

Calling EndInvoke() only returns the below. My runspace tasks are in some case hours long. I can not lose all the output except the last exception. I do not have control over the script blocks as they get passed into my cmdlets.

How do I resolve that?

Exception calling "EndInvoke" with "1" argument(s): " Exception in sb"
At line:1 char:1
+ $j.PowerShell.EndInvoke($j.Job)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : RuntimeException

Solution

  • By the time you call EndInvoke(), you are already too late. There is no way to receive the data from the output stream as all that data is discarded and the only thing you will get is the thrown exception message. Instead, you have to change how you do your initial BeginInvoke() call to allow you to capture the output.

    Using an overloaded BeginInvoke(TInput,TOutput) call, you can both pass your input commands (if needed, or blank), as well as you have to supply a buffer for the output to be stored (of type System.Management.Automation.PSDataCollection[psobject]). So your code looks like this:

    $sb = {
     write-output "Testing 1"
     write-output "Testing 2"
     throw " Exception in sb"
    }
    
    $PowerShell = [powershell]::Create()
    
    [void]$PowerShell.AddScript($sb)
    
    $InputObject = New-Object 'System.Management.Automation.PSDataCollection[psobject]'
    $OutputObject = New-Object 'System.Management.Automation.PSDataCollection[psobject]'
    
    $Handle = $PowerShell.BeginInvoke($InputObject,$OutputObject)
    

    Calling EndInvoke() will give you the error message:

    PS C:\> $PowerShell.EndInvoke($Handle)
    Exception calling "EndInvoke" with "1" argument(s): " Exception in sb"
    At line:1 char:1
    + $PowerShell.EndInvoke($Handle)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : RuntimeException
    

    But the output is stored in the $OutputObject buffer:

    PS C:\> $InputObject
    PS C:\> $OutputObject
    Testing 1
    Testing 2