- Вопрос или проблема
- Проблема
- Разъяснение проблемы
- Устранение неполадок
- Ответ
- Как оценить код выхода команды
- Ответ или решение
- Проблема с оператором && и значением %ErrorLevel% в командной строке Windows
- Введение
- Описание проблемы
- Причины поведения
- Пример с измененной логикой
- Динамическое расширение переменных
- Как правильно обрабатывать коды возврата
- Заключение
Вопрос или проблема
Проблема
Оператор &&
не учитывает значение %ErrorLevel%
. Команда, следующая за оператором, выполняется, несмотря на то, что %ErrorLevel%
равен 99.
Команда
cmd /c exit 99 echo %ErrorLevel% echo %ErrorLevel% && echo %ErrorLevel% echo %ErrorLevel%
Вывод
99 99 99 99
Разъяснение проблемы
Насколько я понимаю, следующее верно:
- Оператор
&&
эквивалентенif "%ErrorLevel%" equ "0"
. - Команда
Echo
не изменяет%ErrorLevel%
.
Устранение неполадок
Я попытался включить отложенное расширение, используя cmd /v:on
, и выполнив следующую команду, но получил тот же вывод. Я протестировал следующую команду в консоли, в .bat файле и в .cmd файле.
setlocal EnableDelayedExpansion
cmd /c exit 99
echo %ErrorLevel%
echo %ErrorLevel% && echo !ErrorLevel!
echo %ErrorLevel%
Использование команды if
изменяет поведение так, как я ожидаю. И замена приведенного ниже кода, чтобы заменить cmd /c exit 99
на cmd /c exit 0
, изменяет вывод на 3 эха 99 вместо 4 эхов 99.
Команда
setlocal EnableDelayedExpansion cmd /c exit 99 echo %ErrorLevel% echo %ErrorLevel% & if "%ErrorLevel%" equ "0" echo !ErrorLevel! echo %ErrorLevel%
Вывод
99 99 99
Ответ
Ответ wildkoala кажется правильным. Операторы &&
и ||
проверяют код выхода предыдущей команды, а не текущее значение в переменной %ErrorLevel%.
Некоторые команды не обновляют переменную %ErrorLevel%. Тем не менее, они все равно будут иметь код выхода.
Более подробно можно прочитать о различии между errorlevel и кодами выхода на ss64 здесь.
Документация часто упрощает объяснение операторов &&
и ||
как проверку, является ли %ErrorLevel% равным 0.
Как оценить код выхода команды
Вы можете использовать команду call
для переменной или скрипта, который заканчивается командой, которую вы хотите оценить. Это заставит переменную %ErrorLevel% обновиться кодом выхода последней команды.
Пример
cmd /v:on
set command1=cmd /c exit 99
set command2=echo hide output^>nul
%command1% & echo !ErrorLevel!
99
%command2% & echo !ErrorLevel!
99
call %command2% & echo !ErrorLevel!
0
call %command1% & echo !ErrorLevel!
99
Оператор &&
только проверяет статус выхода предыдущей команды, в данном случае echo %ErrorLevel%
, не %ErrorLevel%
сам по себе. Даже если ваша предыдущая команда приводит к изменению %ErrorLevel%
, &&
не будет его оценивать.
В результате, echo %ErrorLevel% && echo %ErrorLevel%
выполнится, если echo %ErrorLevel%
вернет код выхода 0 (что и происходит, так как она выполнена успешно). Таким образом, как вы уже выяснили, необходимо использовать оператор if вместо этого.
Ответ или решение
Проблема с оператором &&
и значением %ErrorLevel%
в командной строке Windows
Введение
Вопрос о том, почему оператор &&
не учитывает значение %ErrorLevel%
, вызывает много путаницы среди пользователей Windows, особенно тех, кто активно работает с командной строкой и сценариями .bat/.cmd. Данная статья подробно разъясняет данную проблему, разобравшись в механизмах работы операторов и обработки кодов возврата в Windows.
Описание проблемы
Когда вы выполняете команду, которая изменяет код возврата (например, cmd /c exit 99
), вы ожидаете, что в дальнейшем код обработки ошибок будет зависеть от этого значения. Однако оператор &&
работает по-другому. Рассмотрим команду:
cmd /c exit 99
echo %ErrorLevel%
echo %ErrorLevel% && echo %ErrorLevel%
Вывод будет следующим:
99
99
99
99
В этом примере, несмотря на то что %ErrorLevel%
равен 99, вторая команда echo %ErrorLevel%
выполняется.
Причины поведения
-
Как работает оператор
&&
: Оператор&&
выполняет следующую команду только в случае успешного завершения предыдущей команды (код возврата 0). Он проверяет код возврата непосредственно после выполнения команды, а не текущее значение переменной%ErrorLevel%
. В данном случае в качестве предыдущей команды выступаетecho %ErrorLevel%
, которая выполняется успешно, и, следовательно,echo %ErrorLevel%
выполняется вновь. -
Неизменяемость
%ErrorLevel%
для команд: Командаecho
не изменяет код возврата, и она всегда завершается успешно (0). Поэтому&&
считает, что последующая команда может выполняться.
Пример с измененной логикой
Для правильной проверки кодов возврата следует использовать условие, которое проверяет значение %ErrorLevel%
:
echo %ErrorLevel% & if "%ErrorLevel%" equ "0" echo %ErrorLevel%
Этот подход корректно обрабатывает значение кода возврата, так как if
опирается на фактическое значение, а не на значение переменной.
Динамическое расширение переменных
Использование динамического расширения переменных (setlocal EnableDelayedExpansion
) изменяет способ работы с переменными внутри команд, однако в данном контексте это не решает проблему.
setlocal EnableDelayedExpansion
cmd /c exit 99
echo %ErrorLevel%
echo %ErrorLevel% && echo !ErrorLevel!
Вы получите такой же результат, поскольку оператор &&
все равно проверяет предыдущую команду, а не переменную.
Как правильно обрабатывать коды возврата
Если вы хотите получить корректное поведение от командной строки, рекомендуется использовать команду call
для вызова других команд и получения актуального значения кода возврата. Например:
set command=cmd /c exit 99
call %command% & echo !ErrorLevel!
Это гарантирует получение ожидаемого кода возврата.
Заключение
Оператор &&
в командной строке Windows не учитывает значение переменной %ErrorLevel%
в момент выполнения команды. Он основан на кодах возврата предыдущих команд. Чтобы корректно управлять логикой выполнения команд в зависимости от кода возврата, необходимо использовать конструкции if
, а также call
для выполнения команд внутри контекста, требующего правильного обновления %ErrorLevel%
. Это поможет избежать недоразумений и позволит более точно контролировать поведение сценариев Windows.