Надежный способ проверки ненулевого (ошибочного) кода возврата в командном файле Windows
вступление
Существует много советов по работе с кодами возврата в пакетных файлах (с использованием механизма ERROLEVEL), например
Некоторый совет должен сделать if errorlevel 1 goto somethingbad
в то время как другие рекомендуют использовать %ERRORLEVEL%
переменная и использование ==
, EQU
, LSS
и т. д. Похоже, что проблемы внутри IF
заявления и тому подобное, так что тогда задержка расширения поощряется, но, похоже, она имеет свои причуды.
Вопрос
Что такое надежный (то есть надежный, так что он будет работать практически на любой системе с почти любым кодом возврата) способ узнать, был ли возвращен неверный (ненулевой) код?
Моя попытка
Для базового использования следующее работает нормально, чтобы перехватить любой ненулевой код возврата:
if not errorlevel 0 (
echo error level was nonzero
)
1 ответ
Извините, ваша попытка даже не близка. 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)
Примечание. Я отредактировал свой ответ, чтобы явно очистить любое пользовательское значение уровня ошибки после прочтения комментария Джои к связанному ответу в вопросе. Пользовательский уровень ошибки может маскировать динамическое значение, к которому мы пытаемся получить доступ. Но это работает только если ваш скрипт имеет .bat
расширение. Скрипты с .cmd
Расширение установит ваш ERRORLEVEL в 0, если вы установите или очистите переменную! Что еще хуже, XP установит ERRORLEVEL в 1, если вы попытаетесь отменить определение несуществующей переменной. Вот почему я сначала явно определяю переменную ERRORLEVEL, прежде чем пытаюсь ее очистить!
Если вы находитесь в заключенном в скобки блоке кода, то вы должны использовать отложенное расширение, чтобы получить текущее значение
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)
)
Вот, наконец, "окончательный" тест на ненулевой уровень ошибки, который должен работать при любых обстоятельствах:-)
(
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
)
Последний вопрос:
Перенаправление ввода и / или вывода может завершиться ошибкой по ряду причин. Но ошибки перенаправления не устанавливают уровень ошибки, если только ||
оператор используется. См. Перенаправление файлов в Windows и% errorlevel% для получения дополнительной информации. Таким образом, можно утверждать, что не существует надежного способа проверки ошибок с помощью уровня ошибок. Самый надежный метод (но все же не безошибочный) ||
оператор.