jborean93 / pypsrp

PowerShell Remoting Protocol for Python
MIT License
324 stars 49 forks source link

Retrieving all errors with $ErrorActionPreference = 'Stop' #147

Closed malthe closed 2 years ago

malthe commented 2 years ago

In PowerShell, I'm invoking a bat-file using:

& my-file.bat

With $ErrorActionPreference = 'Stop' I get just one item in ps.streams.error with a not very helpful message.

But without $ErrorActionPreference = 'Stop' (i.e. continue), I am able to capture more errors:

$output = & my-file.bat 2>&1
Write-Output $output

In ps.output I now see multiple errors, some of which contain the actual error.

Looking through the code I don't see an obvious problem which would "stop processing after a first error". But where do the additional error messages go? Swallowed up ... somewhere.

jborean93 commented 2 years ago

I’m not at my computer to verify this but native command output handling is a bit unique, especially with Windows PowerShell. Any lines sent to stderr are treated as error records and because of the error action preference to stop it will stop on the first line. I believe this behaviour has changed in PowerShell 7+ so that stderr is just an error record but is not affected by EAP but WinPS is stuck with the older behaviour.

So to answer your question, the errors are just discarded by PowerShell and not converted to error records. When you redirect to output you no longer have any error records being sent to the error stream that EAP can detect and stop execution. My recommendation is to either:

$ErrorActionPreference = 'Stop'
…
& {
    # this only affects this scope
    $ErrorActionPreference = 'Continue'
    my.bat
}
…
# using redirection we can still have it all split
$stdout = $null
$stderr = . { my.bat args | Set-Variable stdout } 2>&1 | ForEach-Object ToString
If ($LASTEXITCODE) {
    # do something with stderr
}
malthe commented 2 years ago

Setting $ErrorActionPreference = 'Continue' in the child scope is a great trick – thank you for that snippet!

I hope other people will find this answer.