Why does a PowerShell script not end when there is a non-zero exit code when using the call operator and $ErrorActionPerference = "Stop"
?
Using the following example, I get the result managed to get here with exit code 1
:
$ErrorActionPreference = "Stop"
& cmd.exe /c "exit 1"
Write-Host "managed to get here with exit code $LASTEXITCODE"
The Microsoft documentation for the call operator does not discuss what should happen when using call operator, it only states the following:
Runs a command, script, or script block. The call operator, also known as the "invocation operator," lets you run commands that are stored in variables and represented by strings. Because the call operator does not parse the command, it cannot interpret command parameters.
Additionally, if this is expected behaviour, is there any other way to have the call operator cause an error rather than let it continue?
Open a PowerShell console session, type exit , and press the Enter key. The PowerShell console will immediately close.
The $() is the subexpression operator. It causes the contained expressions to be evaluated and it returns all expressions as an array (if there is more than one) or as a scalar (single value).
The return keyword exits a function, script, or script block. It can be used to exit a scope at a specific point, to return a value, or to indicate that the end of the scope has been reached.
The “$_” is said to be the pipeline variable in PowerShell. The “$_” variable is an alias to PowerShell's automatic variable named “$PSItem“. It has multiple use cases such as filtering an item or referring to any specific object.
The return code is not a PowerShell error - it's seen the same way as any other variable.
You need to then act on the variable and throw
an error using PowerShell for you script to see it as a terminating error:
$ErrorActionPreference = "Stop"
& cmd.exe /c "exit 1"
if ($LASTEXITCODE -ne 0) { throw "Exit code is $LASTEXITCODE" }
In almost all my PowerShell scripts, I prefer to "fail fast," so I almost always have a small function that looks something like this:
function Invoke-NativeCommand() {
# A handy way to run a command, and automatically throw an error if the
# exit code is non-zero.
if ($args.Count -eq 0) {
throw "Must supply some arguments."
}
$command = $args[0]
$commandArgs = @()
if ($args.Count -gt 1) {
$commandArgs = $args[1..($args.Count - 1)]
}
& $command $commandArgs
$result = $LASTEXITCODE
if ($result -ne 0) {
throw "$command $commandArgs exited with code $result."
}
}
So for your example I'd do this:
Invoke-NativeCommand cmd.exe /c "exit 1"
... and this would give me a nice PowerShell error that looks like:
cmd /c exit 1 exited with code 1.
At line:16 char:9
+ throw "$command $commandArgs exited with code $result."
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (cmd /c exit 1 exited with code 1.:String) [], RuntimeException
+ FullyQualifiedErrorId : cmd /c exit 1 exited with code 1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With