Вопрос по batch-file, windows – Надежный способ проверки ненулевого (ошибочного) кода возврата в командном файле Windows
Существует множество советов по работе с кодами возврата в пакетных файлах (с использованием механизма ERROLEVEL), например,
Get error code from within a batch file ERRORLEVEL inside IFНекоторый совет должен сделатьif errorlevel 1 goto somethingbad
в то время как другие рекомендуют использовать
%ERRORLEVEL%
переменная и использование==
, EQU
, LSS
и т. д. Похоже, что проблемы внутриIF
заявления и тому подобное, так что тогда задержка расширения поощряется, но, похоже, она имеет свои причуды.
Что является надежным (то есть надежным, так что он будет работать практически на любой системе с почти любым кодом возврата), чтобы узнать, если это плохо (nonzero) код был возвращен?
My attemptДля базового использования следующее, кажется, работает нормально, чтобы поймать любой ненулевой код возврата:
if not errorlevel 0 (
echo error level was nonzero
)
if not errorlevel 0
Истинно, только если уровень ошибки отрицателен.
Если вы знаете, что уровень ошибки никогда не будет отрицательным, то
if errorlevel 1 (echo error level is greater than 0)
Если вы должны учитывать отрицательный уровень ошибки и не входите в блок кода, заключенный в скобки, то
set "errorlevel=1"
set "errorlevel="
if %errorlevel% neq 0 (echo error level is non-zero)
Note - I edited my answer to explicitly clear any user defined errorlevel value after reading Joey's comment to the linked answer in the question. A user defined errorlevel can mask the dynamic value that we are trying to access. But this only works if your script has a .bat
extension. Scripts with .cmd
extension will set your ERRORLEVEL to 0 if you set or clear a variable! To make matters worse, XP will set ERRORLEVEL to 1 if you attempt to undefine a variable that does not exist. That is why I first explicitly define an ERRORLEVEL variable before I attempt to clear it!
Если вы находитесь в заключенном в скобки блоке кода, вы должны использовать отложенное расширение, чтобы получить текущее значение
setlocal enableDelayedExpansion
(
SomeCommandThatMightGenerateAnError
set "errorlevel=1"
set "errorlevel="
if !errorlevel! neq 0 (echo error level is non-zero)
)
Но иногда вы не хотите, чтобы отложенное расширение было включено. Не все потеряно, если вы хотите проверить уровень ошибки сразу после выполнения команды.
(
SomeCommandThatMightGenerateAnError && (echo Success, no error) || (echo There was an error)
)
Если вам абсолютно необходимо проверить динамическое значение ERRORLEVEL без использования отложенного расширения внутри блока в скобках, тогда работает следующее. Но он имеет код обработки ошибок в двух местах.
(
SomeCommandThatMightGenerateAnError
if errorlevel 1 (echo errorlevel is non-zero) else if not errorlevel 0 (echo errorlevel is non-zero)
)
Here, at long last, is the "ultimate" test for non-zero errrolevel that should work under any circumstances :-)
(
SomeCommandThatMightGenerateAnError
set foundErr=1
if errorlevel 0 if not errorlevel 1 set "foundErr="
if defined foundErr echo errorlevel is non-zero
)
Это может даже быть преобразовано в макрос для простоты использования:
set "ifErr=set foundErr=1&(if errorlevel 0 if not errorlevel 1 set foundErr=)&if defined foundErr"
(
SomeCommandThatMightGenerateAnError
%ifErr% echo errorlevel is non-zero
)
Макрос поддерживает круглые скобки и ELSE просто отлично:
%ifErr% (
echo errorlevel is non-zero
) else (
echo errorlevel is zero
)
One last issue:
Перенаправление ввода и / или вывода может завершиться ошибкой по ряду причин. Но ошибки перенаправления делаютnot установить уровень ошибки, если только||
оператор используется. УвидетьПеренаправление файлов в Windows и% errorlevel% для дополнительной информации. Таким образом, можно утверждать, что не существует надежного способа проверки ошибок с помощью уровня ошибок. Самый надежный метод (но все же не безошибочный)||
оператор.