Какие внутренние команды 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, butEXIT /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.