Какие внутренние команды cmd.exe сбрасывают ОШИБКУ в 0 при успешном завершении?

Частым методом обработки ошибок в пакетных сценариях Windows является использование таких вещей, как
if errorlevel 1 ... или же if %errorlevel% neq 0 ..., Часто хочется, чтобы код обработки ошибок сохранил ERRORLEVEL.

Я полагаю, что все внешние команды всегда будут приводить к тому, что ERRORLEVEL будет установлен на какое-то значение, поэтому код обработки ошибок должен сохранять ERRORLEVEL в переменной среды перед выполнением внешней команды.

Но как насчет внутренних команд? Проблема заключается в том, что некоторые внутренние команды сбрасывают ERRORLEVEL в 0, когда они успешны, а некоторые нет. И я не могу найти какую-либо документацию, указывающую, какие команды делают что.

Таким образом, вопрос в том, какие внутренние команды сбрасывают ОШИБКУ в 0 при успешном завершении? Это не общий вопрос о возвращенных кодах ERRORLEVEL, а строго о результатах успеха.

Есть сообщения типа Какой самый простой способ сбросить ERRORLEVEL на ноль? и пакетные файлы Windows:.bat против.cmd? которые дают частичные ответы. Но я никогда не видел полный список.

Примечание: мне было любопытно об этом в течение многих лет. Поэтому я наконец решил провести кучу экспериментов и придумать окончательный ответ. Я публикую эти вопросы и ответы, чтобы поделиться тем, что я нашел.

2 ответа

Решение

Этот ответ основан на экспериментах, которые я проводил под Windows 10. Я сомневаюсь, что есть различия с более ранними версиями Windows, которые используют cmd.exe, но это возможно.

Также обратите внимание - этот ответ не пытается задокументировать результат ERRORLEVEL, когда внутренняя команда обнаруживает ошибку (за исключением крошечного бита, касающегося DEL и ERASE)

Разница между командами не только различна, но и одна команда может вести себя по-разному в зависимости от того, была ли она запущена из командной строки или внутри пакетного сценария с .bat расширение или из пакетного сценария с .cmd расширение.

Следующий набор команд никогда не сбрасывает ERRORLEVEL в 0 при успешном завершении, независимо от контекста, но вместо этого сохраняет предыдущий ERRORLEVEL:

  • ПЕРЕРЫВ
  • ЦБС
  • ECHO
  • ENDLOCAL
  • FOR: Очевидно, что команды в предложении DO могут устанавливать ERRORLEVEL, но успешное FOR с хотя бы одной итерацией не устанавливает ERRORLEVEL в 0 само по себе.
  • ИДТИ К
  • IF: Очевидно, что команды, выполняемые IF, могут устанавливать ERRORLEVEL, но успешный IF не устанавливает ERRORLEVEL в 0 самостоятельно.
  • КЛЮЧИ
  • ПАУЗА
  • POPD
  • RD
  • REM
  • RMDIR
  • СДВИГ
  • НАЧНИТЕ
  • ЗАГЛАВИЕ

Следующий набор команд всегда сбрасывает ERRORLEVEL в 0 в случае успеха, независимо от контекста:

  • CD
  • CHDIR
  • ЦВЕТ
  • COPY
  • ДАТА
  • DEL: всегда очищает ERRORLEVEL, даже если DEL завершается ошибкой (кроме случаев, когда выполняется без аргумента файла)
  • DIR
  • ERASE: всегда очищает ERRORLEVEL, даже если ERASE завершается неудачей. (кроме случаев, когда он запускается без каких-либо аргументов файла).
  • Мэриленд
  • MKDIR
  • MKLINK
  • ПЕРЕЕХАТЬ
  • PUSHD
  • REN
  • ПЕРЕИМЕНОВАТЬ
  • SETLOCAL
  • ВРЕМЯ
  • ТИП
  • VER
  • ПРОВЕРКИ
  • VOL

Тогда есть эти команды, которые не очищают ERRORLEVEL в случае успеха, если они выполняются из командной строки или внутри скрипта с .bat расширение, но очистите ERRORLEVEL до 0, если он выпущен из сценария с .cmd расширение. См. /questions/37874146/paketnyie-fajlyi-windows-bat-protivcmd/37874154#37874154 и https://groups.google.com/forum/#!msg/microsoft.public.win2000.cmdprompt.admin/XHeUq8oe2wk/LIEViGNmkK0J для получения дополнительной информации.

  • ASSOC
  • DPATH
  • FTYPE
  • ДОРОЖКА
  • НЕЗАМЕДЛИТЕЛЬНЫЙ
  • ЗАДАВАТЬ

Наконец, есть эти команды, которые не вписываются ни в одну из предыдущих категорий:

  • CALL: если подпрограмма: или пакетный сценарий CALLed, то ERRORLEVEL управляется исключительно сценарием CALLed или: подпрограммой. Но любой другой тип успешного вызова CALL для команды всегда сбрасывает ERRORLEVEL в 0, если команда CALLed не устанавливает его иначе.
    Пример: call echo OK,

  • EXIT: If used without /B, then the cmd.exe session terminates and there is no more ERRORLEVEL, just the cmd.exe return code. очевидно EXIT /B 0 clears the ERRORLEVEL to 0, but EXIT /B without a value preserves the prior ERRORLEVEL.

I believe that accounts for all internal commands, unless there is an undocumented command that I missed.

Ваше описание CALL команда не завершена:

CALL: Сбрасывает ERRORLEVEL, если команда CALLed не устанавливает его иначе. Пример: call echo OK,

Проверьте этот небольшой пример:

@echo off

call :setTwo
echo Set two: %errorlevel%

call :preserve
echo Preserve: %errorlevel%

call echo Reset
echo Reset: %errorlevel%

call :subNotExists 2> NUL
echo Sub not exist: %errorlevel%

goto :EOF

:setTwo
exit /B 2

:preserve
echo Preserve
exit /B

Выход:

Set two: 2
Preserve
Preserve: 2
Reset
Reset: 0
Sub not exist: 1

CALL Описание должно сказать что-то вроде этого:

  • CALL: Сбрасывает ERRORLEVEL, если команда CALLed не устанавливает его иначе. Пример: call echo OK, но если вызываемая команда является подпрограммой, она сохраняет предыдущий ERRORLEVEL. Если вызываемая подпрограмма не существует, она устанавливает ERRORLEVEL в 1.
Другие вопросы по тегам