Powershell $LastExitCode=0 but $?=False . Redirecting stderr to stdout gives NativeCommandError

Posted by Colonel Panic on Stack Overflow See other posts from Stack Overflow or by Colonel Panic
Published on 2012-05-19T14:36:14Z Indexed on 2012/10/12 21:37 UTC
Read the original article Hit count: 314

Can anyone explain Powershell's surprising behaviour in the second example below? First, a example of sane behaviour:

PS C:\> & cmd /c "echo Hello from standard error 1>&2"; echo "`$LastExitCode=$LastExitCode and `$?=$?"
Hello from standard error
$LastExitCode=0 and $?=True

No surprises. I print a message to standard error (using cmd's echo). I inspect the variables $? and $LastExitCode. They equal to True and 0 respectively, as expected.

However, if I ask Powershell to redirect standard error to standard output over the first command, I get a NativeCommandError:

PS C:\> & cmd /c "echo Hello from standard error 1>&2" 2>&1; echo "`$LastExitCode=$LastExitCode and `$?=$?"
cmd.exe : Hello from standard error
At line:1 char:4
+ cmd <<<<  /c "echo Hello from standard error 1>&2" 2>&1; echo "`$LastExitCode=$LastExitCode and `$?=$?"
    + CategoryInfo          : NotSpecified: (Hello from standard error :String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

$LastExitCode=0 and $?=False

My first question, why the NativeCommandError ?

Secondly, why is $? False when cmd ran successfully and $LastExitCode is 0? Powershell's docs about_Automatic_Variables don't explicitly define $?. I always supposed it is True if and only if $LastExitCode is 0 but my example contradicts that.


Here's how I came across this behaviour in the real-world (simplified). It really is FUBAR. I was calling one Powershell script from another. The inner script:

cmd /c "echo Hello from standard error 1>&2"
if (! $?)
{
    echo "Job failed. Sending email.."
    exit 1
}
# do something else

Running this simply .\job.ps1, it works fine, no email is sent. However, I was calling it from another Powershell script, logging to a file .\job.ps1 2>&1 > log.txt. In this case, an email is sent! Here, the act of observing a phenomenon changes its outcome. This feels like quantum physics rather than scripting!

[Interestingly: .\job.ps1 2>&1 may or not blow up depending on where you run it]

© Stack Overflow or respective owner

Related posts about Windows

Related posts about powershell