Retrieving all errors with $ErrorActionPreference = 'Stop'
malthe opened this issue · 2 comments
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.
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:
- temporary set EAP to continue in a child scope
$ErrorActionPreference = 'Stop'
…
& {
# this only affects this scope
$ErrorActionPreference = 'Continue'
my.bat
}
…
- redirect stderr to a var and output it separately as needed
# 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
}
Setting $ErrorActionPreference = 'Continue'
in the child scope is a great trick – thank you for that snippet!
I hope other people will find this answer.