Не использовать $host.SetShouldExit()
: он не вызывается кодом пользователя. Вместо этого он используется внутри PowerShell в ответ на оператор exit
в коде пользователя .
Просто используйте exit 23
напрямую в вашем скрипте exit1.ps1
, который будет делать то, что вы хотите:
При запуске в сеансе PowerShell скрипт установит код выхода 23
без выхода процесс PowerShell в целом; используйте $LASTEXITCODE
для последующего запроса.
.\exit.ps1; $LASTEXITCODE # -> 23
При запуске через PowerShell CLI :
с -File
, код завершения, установленный сценарием, автоматически становится кодом выхода процесса PowerShell, который может проверить вызывающий; при вызове из cmd.exe
, %ERRORLEVEL%
отражает этот код выхода.
powershell -File .\exit.ps1
:: This outputs 23
echo %ERRORLEVEL%
с -Command
, дополнительная работа необходимо, поскольку PowerShell просто отображает любой ненулевой код выхода на 1
, что приводит к потере указанного c кода выхода; чтобы компенсировать это, просто выполните exit $LASTEXITCODE
в качестве последнего оператора :
powershell -Command '.\exit.ps1; exit $LASTEXITCODE'
:: This outputs 23
echo %ERRORLEVEL%
Для больше информации о том, как PowerShell устанавливает коды выхода , см. Этот ответ .
Если :
, то вы этого не сделаете контролировать, как ваш скрипт вызывается через CLI, но должен гарантировать, что правильный код завершения будет сообщен, даже когда скрипт вызывается через -Command
,
и вы готовы взять на себя риск использования $host.SetShouldExit()
, даже если он не предназначен для прямого использования,
, вы можете попробовать следующее:
function ExitWithCode($exitcode) {
if ([Environment]::CommandLine -match ( # Called via the CLI? (-File or -Command)
' .*?\b' +
[regex]::Escape([IO.Path]::GetFileNameWithoutExtension($PSCommandPath)) +
'(?:\.ps1\b| |$)')
) {
# CAVEAT: While this sets the exit code as desired even with -Command,
# the process terminates instantly.
$host.SetShouldExit($exitcode)
}
else {
# Exit normally, which in interactive session exits the script only.
exit $exitcode
}
}
ExitWithCode 23
Функция ищет имя файла исполняемого скрипта в командной строке процесса, чтобы определить, вызывается ли включающий скрипт напрямую через CLI , через автомат c $PSCommandPath
переменная, которая содержит полный путь скрипта.
Если это так, то применяется вызов $host.SetShouldExit()
, чтобы убедиться, что код выхода установить как задумано даже в случае вызова через -Command
.
Обратите внимание, что это равносильно перепрофилированию эффективного внутреннего .SetShouldExit()
метода.
Удивительно, эта перестановка работает, даже если после вызова сценария внутри строки -Command
появляются дополнительные команды, но учтите, что это неизменно означает, что статус успешного выполнения действительно последней команды - если это не вызов сценария - будет эффективно игнорироваться.
Этот подход не является надежным [1] , но , вероятно, работает достаточно хорошо на практике.
[1]
* Может быть ложных срабатываний , учитывая, что ищется только файл name , без расширения (поскольку -Command
позволяет опустить .ps1
расширение вызываемых скриптов).
* Может быть ложных негативов , если скрипт вызывается с помощью другого скрипта.