Why does PowerShell show the surprising behaviour in the second example below?
First, an 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 documentation about automatic variables doesn'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 as .\job.ps1
, it works fine, and 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! What you do outside the script with the error stream affects the internal behaviour of the script. Observing a phenomenon changes the 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]
!$?
too with the caveat that it apparently doesn't work like expected. – Quota& cmd /c "echo Hello from standard error 1>&2" 2`>`&1
– Helaina2`>`&1
indeed works – Adductnslookup microsoft.com 2`>`&1
givesCan't find server address for '2>&1'
– Adduct& cmd.exe /c nslookup "microsoft.com" 2`>`&1
– Helainacmd
. If you want redirection you need a shell that understands it.nslookup
is just a command that does its thing but it's no shell. – Quota