Powershell некорректно обрабатывает коды выхода из запущенных нативных exe-файлов (не из командлетов).
Допустим у нас есть команда, которая запускает exe-файл и возвращает код отличный от 0 и мы хотим обработать эту ситуацию с помощью Try-Catch.
Вопреки интуитивному ожиданию такая конструкция не сработает:
try { run_buggy_executive.exe run_somthing_else.exe } catch { Wtite-Host "We got an error!!!" }
Мы не получим сообщения We got an error!!! при ненулевом коде возврата из run_buggy_executive.exe, а запущены будут оба исполняемых файла (или команды).
Как же быть?
Вариантов фактически два (https://stackoverflow.com/questions/9948517/how-to-stop-a-powershell-script-on-the-first-error):
- Вручную проверять код выхода (код запуска и проверки можно обернуть в функцию, но фактически способ останется тем же):
try { doSomething -arg myArg if (-not $?) { Write-Error -Message "doSomething Failed..." -ErrorAction Stop } } catch { Write-Error -Message "We have a problem. $PSItem" -ErrorAction Stop }
Тут важно обратить внимание на -ErrorAction Stop - без него будет просто отображение сообщения об ошибке, а не остановка.
Ну или можно использовать throw вместо Write-Error -ErrorAction Stop - Второй вариант - гораздо более практичный, но очень неочевидный - это перенаправление stderr в stdout:
try { doSomething -arg myArg 2>&1 } catch { Write-Error -Message "We have a problem. $PSItem" -ErrorAction Stop }
В итоге - при ошибке код в блоке Try остановится на строке, которая вызвала ошибку и дальше исполнится блок Catch.
Discussion