Почему PowerShell демонстрирует удивительное поведение во втором примере ниже?
Во-первых, пример нормального поведения:
PS C:\> & cmd /c "echo Hello from standard error 1>&2"; echo "'$LastExitCode=$LastExitCode and '$?=$?"
Hello from standard error
$LastExitCode=0 and $?=True
Никаких сюрпризов. Я печатаю сообщение со стандартной ошибкой (используя cmd
echo
). Я проверяю переменные $?
и $LastExitCode
. Как и ожидалось, они равны True и 0 соответственно.
Однако, если я прошу PowerShell перенаправить стандартную ошибку на стандартный вывод по первой команде, я получу ошибку 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
Мой первый вопрос, почему NativeCommandError?
Во-вторых, почему $?
False, когда cmd
успешно запущен и $LastExitCode
равен 0? Документация PowerShell об автоматических переменных явно не определяет $?
. Я всегда предполагал, что это правда, если и только если $LastExitCode
равен 0, но мой пример противоречит этому.
Вот как я столкнулся с таким поведением в реальном мире (упрощенно). Это действительно FUBAR. Я вызывал один сценарий PowerShell из другого. Внутренний скрипт:
cmd /c "echo Hello from standard error 1>&2"
if (! $?)
{
echo "Job failed. Sending email.."
exit 1
}
# Do something else
Запустив это просто как .\job.ps1
, он работает нормально, и электронное письмо не отправляется. Однако я вызывал его из другого скрипта PowerShell, записывая в файл .\job.ps1 2>&1 > log.txt
. В этом случае письмо отправляется! То, что вы делаете вне скрипта с потоком ошибок, влияет на внутреннее поведение скрипта. Наблюдение за явлением меняет результат. Это похоже на квантовую физику, а не на сценарии!
[Интересно: .\job.ps1 2>&1
может взорваться или не взорваться в зависимости от того, где вы его запускаете]