$ LastExitCode = 0, pero $? = False en PowerShell. Redirigir stderr a stdout da NativeCommandError
¿Por qué PowerShell muestra el comportamiento sorprendente en el segundo ejemplo a continuación?
Primero, un ejemplo de comportamiento sano:
PS C:\> & cmd /c "echo Hello from standard error 1>&2"; echo "`$LastExitCode=$LastExitCode and `$?=$?"
Hello from standard error
$LastExitCode=0 and $?=True
No hay sorpresas. Imprimo un mensaje a error estándar (usandocmd
esecho
). Yo inspecciono las variables$?
y$LastExitCode
. Son iguales a Verdadero y 0 respectivamente, según lo esperado.
Sin embargo, si le pido a PowerShell que redirija el error estándar a la salida estándar sobre el primer comando, obtengo un 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
Mi primera pregunta, ¿por qué NativeCommandError?
En segundo lugar, porque es$?
Falso cuandocmd
corrió con éxito y$LastExitCode
es 0? Documentación de PowerShellsobre variables automáticas no define explícitamente$?
. Siempre supuse que es verdad si y solo si$LastExitCode
es 0, pero mi ejemplo contradice eso.
Aquí es cómo me encontré con este comportamiento en el mundo real (simplificado). Realmente es FUBAR. Estaba llamando a un script de PowerShell de otro. El guión interno:
cmd /c "echo Hello from standard error 1>&2"
if (! $?)
{
echo "Job failed. Sending email.."
exit 1
}
# Do something else
Ejecutando esto simplemente como.\job.ps1
, funciona bien, y no se envía ningún correo electrónico. Sin embargo, lo estaba llamando desde otro script de PowerShell, iniciando sesión en un archivo.\job.ps1 2>&1 > log.txt
. En este caso, se envía un correo electrónico! Lo que haga fuera de la secuencia de comandos con la secuencia de error afecta el comportamiento interno de la secuencia de comandos.Observar un fenómeno cambia el resultado. ¡Esto se siente como física cuántica en lugar de scripting!
[Curiosamente:.\job.ps1 2>&1
puede o no explotar dependiendo de donde lo ejecutes]