Подтвердить что ты не робот

Неверный способ проверить ненужный (ошибка) код возврата в пакетном файле Windows

Введение

Там много советов по работе с кодами возврата в пакетных файлах (с использованием механизма ERROLEVEL), например

Некоторые из рекомендаций - сделать if errorlevel 1 goto somethingbad, в то время как другие рекомендуют использовать %ERRORLEVEL% и используя ==, EQU, LSS и т.д. Кажется, что возникают проблемы в операторах IF и т.д., поэтому поощряется замедленная экспансия, но, похоже, она имеет свои собственные причуды.

Вопрос

Что такое надежный (т.е. надежный, поэтому он будет работать практически с любой системой с почти любым кодом возврата), чтобы узнать, был ли возвращен плохой (отличный от нуля) код?

Моя попытка

Для базового использования, похоже, работает нормально, чтобы поймать ненужный код возврата:

if not errorlevel 0 (
    echo error level was nonzero
)
4b9b3361

Ответ 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)

Примечание. Я отредактировал свой ответ, чтобы явно очистить любое заданное пользователем значение уровня ошибок после прочтения комментария Joey к связанному ответу в вопросе. Определенный пользователем уровень ошибок может маскировать динамическое значение, к которому мы пытаемся получить доступ. Но это работает только в том случае, если ваш script имеет расширение .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)
)


Здесь, наконец, есть "окончательный" тест для ненулевого errrelvel, который должен работать при любых обстоятельствах: -)

(
  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%. Поэтому можно утверждать, что нет надежного способа проверки ошибок с помощью уровня ошибок. Самый надежный метод (но еще не непогрешимый) - это оператор ||.