Почему не работает errorlevel в цикле
Перейти к содержимому

Почему не работает errorlevel в цикле

  • автор:

IF – оператор условного выполнения команд в командных файлах Windows

NOT — Указывает, что Windows должна выполнить эту команду, только если условие является ложным.

ERRORLEVEL число — Условие является истинным, если код возврата последней выполненной программы не меньше указанного числа.

строка1==строка2 — Условие является истинным, если указанные строки совпадают.

EXIST имя_файла — Условие является истинным, если файл с указанным именем существует.

команда — Задает команду, выполняемую при истинности условия. За этой командой может следовать ключевое слово ELSE. В случае, если указанное условие ложно, будет выполнена команда, находящаяся после слова ELSE.

Предложение ELSE должно располагаться в той же строке, что и команда, следующая за ключевым словом IF. Например:

IF EXIST имя_файла. (
del имя_файла.
) ELSE (
echo имя_файла. missing.
)

Следующий пример содержит ОШИБКУ, поскольку команда del должна заканчиваться переходом на новую строку:

IF EXIST имя_файла. del имя_файла. ELSE echo имя_файла. Missing

Следующий пример также содержит ОШИБКУ, поскольку команда ELSE должна располагаться в той же строке, что и команда, следующая за IF:

IF EXIST имя_файла. del имя_файла.
ELSE echo имя_файла. missing
Вот правильный пример, где все команды расположены в одной строке:

IF EXIST имя_файла. (del имя_файла.) ELSE echo имя_файла. Missing

Изменение команды IF при включении расширенной обработки команд:

IF [/I] строка1 оператор_сравнения строка2 команда
IF CMDEXTVERSION число команда
IF DEFINED переменная команда

где оператор_сравнения принимает следующие значения:

EQU — равно
NEQ — не равно
LSS — меньше
LEQ — меньше или равно
GTR — больше
GEQ — больше или равно,

а ключ /I , если он указан, задает сравнение текстовых строк без учета регистра. Ключ /I можно также использовать и в форме строка1==строка2 команды IF. Сравнения проводятся по общему типу данных, так что если строки 1 и 2 содержат только цифры, то обе строки преобразуются в числа, после чего выполняется сравнение чисел.

Условие CMDEXTVERSION применяется подобно условию ERRORLEVEL, но значение сравнивается с внутренним номером версии текущей реализации расширенной обработки команд. Первая версия имеет номер 1. Номер версии будет увеличиваться на единицу при каждом добавлении существенных возможностей расширенной обработки команд. Если расширенная обработка команд отключена, условие CMDEXTVERSION никогда не бывает истинно.

Условие DEFINED применяется подобно условию EXIST , но принимает в качестве аргумента имя переменной среды и возвращает истинное значение, если эта переменная определена.

Строка %ERRORLEVEL% будет развернута в строковое представление текущего значения кода ошибки ERRORLEVEL, за исключением ситуации, когда уже имеется переменная среды с именем ERRORLEVEL; в подобном случае подставляется значение этой переменной. Например, с помощью данной строки можно выполнить следующее:

goto answer%ERRORLEVEL%
:answer0
echo Получен код возврата 0
:answer1
echo Получен код возврата 1

Допускается и применение описанных выше операторов числового сравнения:

IF %ERRORLEVEL% LEQ 1 goto okay

Строка %CMDCMDLINE% будет развернута в исходную командную строку, переданную CMD.EXE до любой обработки, за исключением ситуации, когда уже определена переменная среды с именем CMDCMDLINE; в подобном случае подставляется значение этой переменной.

Строка %CMDEXTVERSION% будет развернута в строку, представляющую собой текущее значение CMDEXTVERSION, за исключением ситуации, когда уже имеется переменная среды с именем CMDEXTVERSION; в подобном случае подставляется значение этой переменной.

Если параметр командной строки не задан, то пользователю выдается сообщение об ошибке.

@echo off
REM Проверить наличие имени файла, задаваемого в качестве параметра %1
REM Если параметр %1 пустой – переход на метку error
if «%1» EQU «» goto error
REM Если параметр задан, создаем пустой файл, копированием из устройства nul
copy nul «%1»
exit
:error
ECHO File name required ! Must be — %~n0 filename.ext
:exit

Примеры вывода для отвечающего и не отвечающего узлов:

Ответ от 192.168.1.1: число байт=32 время=1мс TTL=64 — если устройство с данным IP-адресом доступно;
Превышен интервал ожидания для запроса. — если устройство не отвечает;

Команда find /I «TTL» возвращает код ERRORLEVEL равный 0 , если строка «TTL» присутствует в результате выполнения ping . Ключ /I имеет смысл использовать, чтобы результат не зависил от того, строчные или заглавные символы составляют строку «ttl».
Результат работы командного файла записывается в текстовый файл iplist.txt

@ECHO OFF
REM Постоянная часть IP-адреса
set IPTMP=192.168.1.
REM Количество пингуемых узлов
set N=254
rem С какого адреса начать — начальное значение » хвоста » IP- адреса X.X.X.IPMIN
set /A IPMIN=1
ECHO %DATE% Опрос пингом %N% адресов начиная с %IPTMP%%IPMIN% >> iplist.txt
rem M0 — метка для организации цикла
:M0
rem Переменная IPFULL — полное значение текущего IP-адреса
set IPFULL=%IPTMP%%IPMIN%
rem Если » хвост «больше N – перейти к завершению работы
IF %IPMIN% GTR %N% GOTO ENDJOB
ping -n 1 %IPFULL% | find /I «TTL»
if %ERRORLEVEL%==0 Echo %IPFULL% >> iplist.txt
rem Сформируем следующий IP-адрес
set /A IPMIN=%IPMIN% + 1
rem Перейдем на выполнение следующего шага
GOTO M0
rem Завершение работы
:endjob
exit

Существуют некоторые особенности реализации командного интерпретатора CMD.EXE , которые необходимо учитывать при обработке значений переменных внутри циклов IF и FOR . Использование значений переменных внутри скобок, требует изменения стандартного режима интерпретации командного процессора. Разработчиками предусмотрена возможность запуска CMD.EXE с параметром /V:ON , что включает разрешение отложенного расширения переменных среды с применением символа восклицательного знака ( ! ) в качестве разделителя. То есть, параметр /V:ON разрешает использовать !var! в качестве значения переменной var во время выполнения внутри циклов команд FOR и IF . Но на практике чаще используется возможность локального включения данного режима внутри командного файла специальной директивой:

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

FOR … (
IF !ERRORLEVEL!==0 вместо %ERRORLEVEL%==0

)

&nbsp &nbsp В русскоязычной справке команды IF имеется ошибка, которая много лет переходит из версии в версию — вместо оператора EQU — равно , указано EQL — равно

Почему не работает errorlevel в цикле

Сообщения: 53126
Благодарности: 15415

Конфигурация компьютера
Процессор: AMD Ryzen 7 7800X3D
Материнская плата: Gigabyte B650E Aorus Master
Память: Kingston Fury Renegade DDR5-6000 32GB (2×16)
HDD: Samsung SSD 850 PRO 256GB, 980 PRO 1TB
Видеокарта: Gainward GeForce RTX 3080 追风
Блок питания: be quiet! Straight Power 11 650W
Монитор: ASUS VG248QE 24″
ОС: Windows 10 Pro x64
Прочее: корпус Fractal Design Define R4
setlocal enabledelayedexpansion for /f "skip=1 tokens=1,2 delims=|" %%i in (%1) do ( for /f "delims=" %%k in (%%i.txt) do ( something.exe %%k %%i echo !errorlevel! ) )

EnableDelayedExpansion — позднее связывание.
Это сообщение посчитали полезным следующие участники:

Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Сообщения: 1025
Благодарности: 180

Конфигурация компьютера

А к переменным, заключенным в !! можно применять разные :~0,-1?

——-
echo 127.0.0.1 google.ru >> %systemroot%\system32\drivers\etc\hosts && ipconfig /flushdns && echo Я ничего не трогал, оно само!

Сообщения: 27449
Благодарности: 8086

Цитата apozlevich:

А к переменным, заключенным в !! можно применять разные :~0,-1? »

Это сообщение посчитали полезным следующие участники:

Сообщения: 26
Благодарности: 1

Подниму тему.
есть листинг:

@ECHO off @COLOR 4 @CHCP 866 SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION CLS :Start For /F "Tokens=2*" %%I In ('Reg Query "HKCU\Software\Microsoft\Shared\UcClient" /V ConfigurationMode') Do SET key=%%J IF %ERRORLEVEL%==0 ( echo 1 pause ) echo 0 pause

просто ищет по реестру ключ.
ключ есть — %errorlevel%=0
ключа нет- %errorlevel%=0 но в консоли пишет, что «ошибка-мол, нет такого» значит место указано верно

как заставить реагировать %errorlevel% на наличие\отсутствие ключа в реестре?

Сообщения: 27449
Благодарности: 8086

Instant_SR, в данном случае Вы видите errorlevel от команды «for /f».

Цитата Instant_SR:

как заставить реагировать %errorlevel% на наличие\отсутствие ключа в реестре? »
@echo off setlocal enableextensions enabledelayedexpansion for /f "usebackq tokens=2*" %%i in ( `reg.exe query "HKCU\Software\Microsoft\Shared\UcClient" /v "ConfigurationMode" 2^>nul ^| find.exe /i "ConfigurationMode"` ) do set sConfigurationMode=%%j if defined sConfigurationMode ( echo ConfigurationMode: [%sConfigurationMode%]. ) else ( echo Parameter not exists. ) endlocal exit /b 0

AHK: ловим ошибки в цикле

Добрый день.
Просмотрел информацию о ErrorLevel, с целью продолжения цикла, когда в нем произошла ошибка.
Но необходимого не добился.
А именно, хочу добиться, когда происходит ошибка в программе, где запущен скрипт, скрипт записывал ошибку в лог (это смогу) и продолжал дальше итерации цикла.

loop < //если ошибка, записываем в log и продолжаем дальше //тут что-то происходит >

2 Ответ от ypppu 2013-10-19 12:19:20

  • ypppu
  • Разработчик
  • Неактивен

Re: AHK: ловим ошибки в цикле

После каждой команды проверяем состояние ErrorLevel. Если не равно нулю, записываем информацию об ошибке.

Антон Иваненко (Дед Мазай) пишет:

ErrorLevel

Это встроенная переменная, призванная отображать успешность или неуспешность выполнения каких-либо команд (однако, не все команды поддерживают работу с ErrorLevel). Значение ErrorLevel, равное нулю, обычно свидетельствует об удачном завершении процесса, любое другое значение, отличное от нуля — о неудаче. Значения для переменной ErrorLevel вы можете устанавливать самостоятельно.

Особо отметим, что применение переменной ErrorLevel вместе с командой RunWait позволяет нам определить успешность выполнения программы с последующим её закрытием. Большинство программ, если их работа завершена успешно, имеют код возврата, равный нулю.

Каждый поток (thread) содержит своё собственное значение ErrorLevel. При этом, если работа текущего потока прервана другим потоком, то по возобновлению работы наш текущий поток будет иметь своё собственное значение ErrorLevel, а не значение ErrorLevel прервавшего его потока.

Примечание: учитывая то, что некоторые команды выдают значение ErrorLevel большее, чем 1, наилучшим способом будет не проверять, имеет ли переменная ErrorLevel значение 1, а имеет ли переменная ErrorLevel значение, отличное от нуля.

WinWait, MyWindow, , 1 ; ищем в течение 1 секунды, существует ли окно с названием MyWindow. if ErrorLevel ; данная запись означает, что переменная ErrorLevel имеет значение, отличное от нуля. MsgBox, Окно не обнаружено. else MsgBox, Окно успешно обнаружено.

ERRORLEVEL это не %ERRORLEVEL% [Статья]

Author24 — интернет-сервис помощи студентам

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

Да, действительно. Отключаем расширения для команд и переменная ErrorLevel уже не раскрывается в код возврата ошибки:

1 2 3 4 5
@echo off Setlocal DisableExtensions CMD /C EXIT 3 echo %errorlevel% pause

Полезняшка:
Поскольку ErrorLevel — является командой, а не переменной.
Для ее работы не требуется использовать отложенное расширение переменных среды.
Значит, в циклах, под скобками или в однострочной команде можно писать просто:

1 2 3 4
( CMD /C EXIT 2 if errorlevel 1 (echo Ошибка) else (echo Успех) )

В примере ниже использованы 2 способа раскрытия + сравнение через команду errorlevel:

1 2 3 4 5 6 7 8 9 10 11
@echo off Setlocal EnableDelayedExpansion ( CMD /C EXIT 3 if errorlevel 3 echo errorlevel as Command is CATCHED if %errorlevel%==3 echo %%errorlevel%% is CATCHED if !errorlevel!==3 echo DelayedExpansion errorlevel is CATCHED ) echo. CMD /C EXIT 4& if errorlevel 3 echo errorlevel = 3 или больше pause
1 2 3 4
rem this next command sets the error level to zero CMD /C EXIT 0 set ERRORLEVEL=1 if ERRORLEVEL 1 echo Does this print?

Сообщение не будет отображено, поскольку переменная ERRORLEVEL не имеет никакого влияния на уровень ошибки. Это просто переменная, имя которой совпадает с концепцией командного процессора.

Общая идея — да. А вот пример работает не совсем так, как Вы предполагаете из вышесказанных слов.
Дело в том, что сама команда set тоже возвращает после своего выполнения код возврата. Он = 0.
Проверим?

1 2 3
CMD /C EXIT 5 set ERRORLEVEL=1 if ERRORLEVEL 5 echo Does this print?

В ответ ничего не получим. Т.к. настоящий код возврата (не переменная) = 0.

Главные выводы:

1) Переменная %ERRORLEVEL% и код возврата ошибки — это не всегда одно и тоже.

2) IF ERRORLEVEL N — это команда, которая дает TRUE, если код возврата ошибки при выполнении предыдущей команды >= N, где N — это число (не переменная).

3) Если включен режим расширения для команд (а он включен по-умолчанию), то
%errorlevel% = сначала процессор смотрит определена ли переменная, иначе получает код возврата ошибки.

4) Такие команды как if, echo. не влияют на код ошибки.

5) Командой ErrorLevel удобно сравнивать код возврата ошибки внутри скобок, циклов, однострочной команде,
т.к. не нужно использовать конструкцию !errorlevel!, а это дает дополнительный прирост в скорости работы.

6) Конструкции вида if %errorlevel%==0 нужно использовать с осторожностью, т.к. отключенный в реестре пользователя режим расширения команд приведет к падению работы скрипта.
Обязательно используйте кавычки: if «%errorlevel%»==»0» или не забывайте принудительно включать директиву SetLocal EnableExtensions в пакетный файл.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *