cmd код возврата последней команды

ERRORLEVEL это не %ERRORLEVEL%

Проверка IF ERROR LEVEL n срабатывает, если уровень ошибки n или выше. Это, вероятно, потому, что многие программы выражают разную степень ошибки все большими и большими кодах выхода. К примеру, программа diff имеет 3 кода выхода: «0» означает, что файлы одинаковые, «1» — разные, «2» — случилось что-то страшное. Некоторые программы используют код выхода «0» для успеха и все остальное для ошибки.

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 BANKBALANCE=$1 000 000,00

«Эй, когда я пытаюсь снять денег, у меня ошибка — „недостаточно денег на счету“».

То же поведение и у %CD% : если вы не установили переменную с таким именем, подставляется текущий каталог командного процессора. Но изменить каталог при помощи set CD=C:\Windows нельзя.

Вероятно, есть несколько причин для такого поведения:
— Чтобы можно было вывести уровень ошибки в лог:
ECHO error level is %ERRORLEVEL%>logfile
— Чтобы можно было выполнять другие сравнения с уровнем ошибки — например, чтобы проверять равенство:
IF %ERRORLEVEL% EQU 1 echo Different!

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

Источник

Коды возврата ошибок (расшифровки ErrorLevel)*

Коды возврата ошибок (встроенных команд и других программ)

Порядок получения код возврата
Запускаем приложение, следующей командой проверяем переменную %ErrorLevel%. Есть еще такие варианты написания.
Например,

В языках высокого уровня код возврата можно получить API функцией:

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

либо указав число, которое вернет основная функция,
например main в C++:

Перечень ErrorLevel в этой теме:

Параноя возврата ошибок. Стоит ли проверять каждое действие? Когда останавливаться?
Если. если..если.. Партянка будет длинной.. Например, через 10 лет села батарейка-системная.

cmd код возврата последней команды. tick. cmd код возврата последней команды фото. cmd код возврата последней команды-tick. картинка cmd код возврата последней команды. картинка tick. Проверка IF ERROR LEVEL n срабатывает, если уровень ошибки n или выше. Это, вероятно, потому, что многие программы выражают разную степень ошибки все большими и большими кодах выхода. К примеру, программа diff имеет 3 кода выхода: «0» означает, что файлы одинаковые, «1» — разные, «2» — случилось что-то страшное. Некоторые программы используют код выхода «0» для успеха и все остальное для ошибки.Коды возврата
Код возврата 2. Причина: ошибки работы встроенных средств оболочки. Мой вопрос: какие есть у.

sov44, ну там не так много.

Это наверное больше вопрос ко мне, что надо бы развивать тему, раз предложил =)
Badger, все это время, готового не находил по встроенным командам (ай-да и не искал).
Если что найдете, выкладываем. Пока информации 0. Есть только по другим (внешним) программам, вроде WinRAR.

А для тестирования вручную нужно готовить среду, чтобы испытать команды в разных ситуациях (то ли это нехватка прав, работа с заблокированным объектом) и т.д.

По другой предложенной темы (ключи) инфы довольно много.

Ну что же начнем собирать.

0Операция успешно завершена.1Предупреждение. Произошли некритические ошибки.2Произошла критическая ошибка.3Неверная контрольная сумма CRC32. Данные повреждены.4Предпринята попытка изменить заблокированный архив.5Произошла ошибка записи на диск.6Произошла ошибка открытия файла.7Ошибка при указании параметра в командной строке.8Недостаточно памяти для выполнения операции.9Ошибка при создании файла.10Нет файлов, удовлетворяющих указанной маске, и параметров.255Операция была прервана пользователем.

Ок, Charles Kludge, исправился. Раз некоторые приложения для кода возврата выделяют буфер DWORD,
думаю, будет нелишним опубликовать и такие значения:

Ясно, значит у меня ответ вернуло 2-байтовый. FFFFFFFFC000013A.

P.S. Тестировал через

Видать, индусы поняли, чтобы возвращать DWORD, придётся писать очередной костыль и забили.:jokingly:

Провел небольшой тест.

Один раз получил странную ошибку. Copy скопировала файл, после чего написала, что «я такого имени не знаю. » =)) Error 9009

По итогам +Errorlevel:

0Успешное завершение/Program suseccfully completed.4Файл не найден/The system cannot find the file specified.4Доступ запрещён/Access is denied. Нет прав доступа к ресурсу.4Невозможно скопировать файл поверх самого себя/The file cannot be copied onto itself

errorlevel = 0, даже, если пользователь ответил «Не заменять файл».

Также видим, что в случаях с защищенной правами папкой или когда файл не существует
мы получаем Errorlevel 1 (а не ожидаемые дефолтовые 5 и 2 соответственно).

0Успешное завершение/Program suseccfully completed.1Файл не найден/The system cannot find the file specified.1Доступ запрещён/Access is denied. Нет прав доступа к ресурсу.1Невозможно скопировать файл поверх самого себя/The file cannot be copied onto itself

errorlevel = 0, даже если пользователь ответил «Не заменять файл»
Чтобы консоль задала этот вопрос:
1) для одиночного файла нужно указать ключ /-y

250 МБ затрачивается на

1,5 сек. больше времени. Не знаю, что именно оно проверяет, но уж файл точно целиком не считывается.

Из предыдущего поста видно, что команда copy возвращает только коды 0, 1,
что есть совсем не айс.

Я написал надстройку, которая согласовывает ошибки согласно таблице, приведенной Charles Kludge.
Естественно, это просто демо, экспериментальный набросок кода.

Robocopy

HexDecimalMeaning
0×1016Serious error. Robocopy did not copy any files.
Either a usage error or an error due to insufficient access privileges
on the source or destination directories.
0×088Some files or directories could not be copied
(copy errors occurred and the retry limit was exceeded).
Check these errors further.
0×044Some Mismatched files or directories were detected.
Examine the output log. Some housekeeping may be needed.
0×022Some Extra files or directories were detected.
Examine the output log for details.
0×011One or more files were copied successfully (that is, new files have arrived).
0×000No errors occurred, and no copying was done.
The source and destination directory trees are completely synchronized.

Таким Batch-файлом получим короткое описание ошибок.
0Нет ошибок1Предупреждение (Не фатальная ошибка(и)).Например, один или более файлов были блокированы другим приложением, таким образом, они не были сжаты.2Фатальная ошибка7Ошибка командной строки8Недостаточно памяти для операции255Пользователь остановил процесс

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Коды ошибок, Коды ошибок для пользователей (не для мастеров)
ОшибкаПричинаE10проблемы подачи воды. Проверьте не закрыт ли кран, не забита ли сеточка, достаточно.

Krups Коды ошибок
Привезли десяток машинок Krups на ремонт, скиньте, пожалуйста, коды ошибок, чтобы не ползать за.

Коды ошибок в BAss
Всем привет. Кто знает как исправить ошибки Error codes list 0 BASS_OK 1 BASS_ERROR_MEM 2.

Коды ошибок Windows
Вам приходилось встречать при работе на компьютере раздражающие всплывающие окна с указанием.

Коды ошибок смартфонов!
После номера ошибки указывается название и описание. Общие ошибки: (-1)Not Found: не удалось.

Источник

Проверка кода завершения предыдущей команды

Еще один способ использования команды IF — это проверка кода завершения (кода выхода) предыдущей команды. Синтаксис для IF в этом случае имеет следующий вид:

IF [NOT] ERRORLEVEL число команда1 [ELSE команда2]

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

Составим, например, командный файл, который бы копировал файл my.txt на диск C: без вывода на экран сообщений о копировании, а в случае возникновения какой-либо ошибки выдавал предупреждение:

XCOPY my.txt C:\ > NUL

REM Проверка кода завершения копирования

IF ERRORLEVEL 1 GOTO ErrOccurred

ECHO Копирование выполнено без ошибок.

ECHO При выполнении команды XCOPY возникла ошибка!

В операторе IF ERRORLEVEL … можно также применять операторы сравнения чисел, приведенные в табл. 3.2. Например:

IF ERRORLEVEL LEQ 1 GOTO Case1

Иногда более удобным для работы с кодами завершения программ может оказаться использование переменной %ERRORLEVEL%. (строковое представление текущего значения кода ошибки ERRORLEVEL ).

Проверка версии реализации расширенной обработки команд

Наконец, для определения внутреннего номера версии текущей реализации расширенной обработки команд применяется оператор IF в следующем виде:

IF CMDEXTVERSION число команда1 [ELSE команда2]

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

Организация циклов

В командных файлах для организации циклов используются несколько разновидностей оператора FOR, которые обеспечивают следующие функции:

· выполнение заданной команды для всех элементов указанного множества;

· выполнение заданной команды для всех подходящих имен файлов;

· выполнение заданной команды для всех подходящих имен каталогов;

· выполнение заданной команды для определенного каталога, а также всех его подкаталогов;

· получение последовательности чисел с заданными началом, концом и шагом приращения;

· чтение и обработка строк из текстового файла;

· обработка строк вывода определенной команды.

Цикл FOR … IN … DO …

Самый простой вариант синтаксиса команды FOR для командных файлов имеет следующий вид:

FOR %%переменная IN (множество)

DO команда [параметры]

Перед названием переменной должны стоять именно два знака процента (%%), а не один, как это было при использовании команды FORнепосредственно из командной строки.

Сразу приведем пример. Если в командном файле заданы строки

FOR %%i IN (Раз,Два,Три) DO ECHO %%i

то в результате его выполнения на экране будет напечатано следующее:

Параметр множество в команде FOR задает одну или более текстовых строк, разделенных запятыми, которые вы хотите обработать с помощью заданной команды. Скобки здесь обязательны. Параметр команда [параметры] задает команду, выполняемую для каждого элемента множества, при этом вложенность команд FOR на одной строке не допускается. Если в строке, входящей во множество, используется запятая, то значение этой строки нужно заключить в кавычки. Например, в результате выполнения файла с командами

FOR %%i IN («Раз,Два»,Три) DO ECHO %%i

на экран будет выведено

Параметр %%переменная представляет подставляемую переменную (счетчик цикла), причем здесь могут использоваться только имена переменных, состоящие из одной буквы. При выполнении команда FOR заменяет подставляемую переменную текстом каждой строки в заданном множестве, пока команда, стоящая после ключевого слова DO, не обработает все такие строки.

Чтобы избежать путаницы с параметрами командного файла %0 — %9, для переменных следует использовать любые символы кроме 0 – 9.

Параметр множество в команде FOR может также представлять одну или несколько групп файлов. Например, чтобы вывести в файл список всех файлов с расширениями txt и prn, находящихся в каталоге C:\TEXT, без использования команды DIR, можно использовать командный файл следующего содержания:

FOR %%f IN (C:\TEXT\*.txt C:\TEXT\*.prn) DO ECHO %%f >> list.txt

При таком использовании команды FOR процесс обработки продолжается, пока не обработаются все файлы (или группы файлов), указанные во множестве.

Цикл FOR /D … IN … DO …

Следующий вариант команды FOR реализуется с помощью ключа /D:

FOR /D %%переменная IN (набор) DO команда [параметры]

В случае, если набор содержит подстановочные знаки, то команда выполняется для всех подходящих имен каталогов, а не имен файлов. Скажем, выполнив следующий командный файл:

FOR /D %%f IN (C:\*.*) DO ECHO %%f

мы получим список всех каталогов на диске C:, например:

Цикл FOR /R … IN … DO …

С помощью ключа /R можно задать рекурсию в команде: FOR:

FOR /R [[диск:]путь] %%переменная IN (набор)

DO команда [параметры]

В этом случае заданная команда выполняется для каталога [диск:]путь, а также для всех подкаталогов этого пути. Если после ключа R не указано имя каталога, то выполнение команды начинается с текущего каталога. Например, для распечатки всех файлов с расширением txt в текущем каталоге и всех его подкаталогах можно использовать следующий пакетный файл:

FOR /R %%f IN (*.txt) DO PRINT %%f

Если вместо набора указана только точка (.), то команда проверяет все подкаталоги текущего каталога. Например, если мы находимся в каталоге C:\TEXT с двумя подкаталогами BOOKS и ARTICLES, то в результате выполнения файла:

FOR /R %%f IN (.) DO ECHO %%f

на экран выведутся три строки:

Цикл FOR /L … IN … DO …

Ключ /L позволяет реализовать с помощью команды FOR арифметический цикл, в этом случае синтаксис имеет следующий: вид:

FOR /L %%переменная IN (начало,шаг,конец) DO команда [параметры]

Здесь заданная после ключевого слова IN тройка (начало,шаг,конец) раскрывается в последовательность чисел с заданными началом, концом и шагом приращения. Так, набор (1,1,5) раскрывается в (1 2 3 4 5), а набор (5,-1,1) заменяется на (5 4 3 2 1). Например, в результате выполнения следующего командного файла:

FOR /L %%f IN (1,1,5) DO ECHO %%f

переменная цикла %%f пробежит значения от 1 до 5, и на экране напечатаются пять чисел:

Числа, получаемые в результате выполнения цикла FOR /L, можно использовать в арифметических вычислениях. Рассмотрим командный файл my.bat следующего содержания:

FOR /L %%f IN (1,1,5) DO CALL :2 %%f

В третьей строке в цикле происходит вызов нового контекста файла my.bat с текущим значением переменной цикла %%f в качестве параметра командной строки, причем управление передается на метку :2 (см. описание CALL в разделе «Изменения в командах перехода»). В шестой строке переменная цикла умножается на десять, и результат записывается в переменную M. Таким образом, в результате выполнения этого файла выведется следующая информация:

Цикл FOR /F … IN … DO …

Самые мощные возможности (и одновременно самый запутанный синтаксис) имеет команда: FOR с ключом /F:

FOR /F [«ключи»] %%переменная IN (набор)

DO команда [параметры]

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

По умолчанию ключ /F выделяет из каждой строки файла первое слово, очищенное от окружающих его пробелов. Пустые строки в файле пропускаются. Необязательный параметр «ключи» служит для переопределения заданных по умолчанию правил обработки строк. Ключи представляют собой заключенную в кавычки строку, содержащую приведенные в табл. 3.3 ключевые слова:

Таблица 3.3. Ключи в команде FOR /F
КлючОписание
EOL=CОпределение символа комментариев в начале строки (допускается задание только одного символа)
SKIP=NЧисло пропускаемых при обработке строк в начале файла
DELIMS=XXXОпределение набора разделителей для замены заданных по умолчанию пробела и знака табуляции
TOKENS=X,Y,M-NОпределение номеров подстрок, выделяемых из каждой строки файла и передаваемых для выполнения в тело цикла

При использовании ключа TOKENS=X,Y,M-N создаются дополнительные переменные. Формат M-N представляет собой диапазон подстрок с номерами от M до N. Если последний символ в строке TOKENS= является звездочкой, то создается дополнительная переменная, значением которой будет весь текст, оставшийся в строке после обработки последней подстроки.

Разберем применение этой команды на примере пакетного файла parser.bat, который производит разбор файла myfile.txt:

IF NOT EXIST myfile.txt GOTO :NoFile

FOR /F «EOL=; TOKENS=2,3* DELIMS=, » %%i IN

(myfile.txt) DO @ECHO %%i %%j %%k

ECHO Не найден файл myfile.txt!

Здесь во второй строке производится проверка наличия файла myfile.txt; в случае отсутствия этого файла выводится предупреждающее сообщение. Команда FOR в третьей строке обрабатывает файл myfile.txt следующим образом:

Пропускаются все строки, которые начинаются с символа точки с запятой ( EOL=; ).

Вторая и третья подстроки из каждой строки передаются в тело цикла, причем подстроки разделяются пробелами (по умолчанию) и/или запятыми ( DELIMS=,).

В теле цикла переменная %%i используется для второй подстроки, %%j — для третьей, а %%k получает все оставшиеся подстроки после третьей.

В нашем примере переменная %%i явно описана в инструкции FOR, а переменные %%j и %%k описываются неявно с помощью ключа TOKENS=. Например, если в файле myfile.txt были записаны следующие три строки:

ААА ББББ ВВВВ,ГГГГГ ДДДД

то в результате выполнения пакетного файла parser.bat на экран выведется следующее:

ББББ ВВВВ ГГГГГ ДДДД

Ключ TOKENS= позволяет извлечь из одной строки файла до 26 подстрок, поэтому запрещено использовать имена переменных, начинающиеся не с букв английского алфавита (a–z). Следует помнить, что имена переменных FOR являются глобальными, поэтому одновременно не может быть активно более 26 переменных.

Команда FOR /F также позволяет обработать отдельную строку. Для этого следует ввести нужную строку в кавычках вместо набора имен файлов в скобках. Строка будет обработана так, как будто она взята из файла. Например, файл следующего содержания:

FOR /F «EOL=; TOKENS=2,3* DELIMS=, » %%i IN

(«ААА ББББ ВВВВ,ГГГГГ ДДДД») DO @ECHO %%i %%j %%k

при своем выполнении напечатает

ББББ ВВВВ ГГГГГ ДДДД

Вместо явного задания строки для разбора можно пользоваться переменными среды, например:

SET M=ААА ББББ ВВВВ,ГГГГГ ДДДД

FOR /F «EOL=; TOKENS=2,3* DELIMS=,

» %%i IN («%M%») DO @ECHO %%i %%j %%k

Наконец, команда FOR /F позволяет обработать строку вывода другой команды. Для этого следует вместо набора имен файлов в скобках ввести строку вызова команды в апострофах (не в кавычках!). Строка передается для выполнения интерпретатору команд cmd.exe, а вывод этой команды записывается в память и обрабатывается так, как будто строка вывода взята из файла. Например, следующий командный файл:

ECHO Имена переменных среды:

FOR /F «DELIMS==» %%i IN (‘SET’) DO ECHO %%i

выведет перечень имен всех переменных среды, определенных в настоящее время в системе.

В цикле FOR допускается применение тех же синтаксических конструкций (операторов), что и для заменяемых параметров (табл. 3.4).

Таблица 3.4. Операторы для переменных команды FOR
ОператорыОписание
%

Fi

Переменная %i расширяется до полного имени файла
%

Di

Из переменной %i выделяется только имя диска
%

Pi

Из переменной %i выделяется только путь к файлу
%

Ni

Из переменной %i выделяется только имя файла
%

Xi

Из переменной %i выделяется расширение имени файла
%

Si

Значение операторов N и X для переменной %i изменяется так, что они работают с кратким именем файла

Если планируется использовать расширения подстановки значений в команде FOR, то следует внимательно подбирать имена переменных, чтобы они не пересекались с обозначениями формата.

Например, если мы находимся в каталоге C:\Program Files\Far и запустим командный файл следующего содержания:

FOR %%i IN (*.txt) DO ECHO %%

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

Источник

Коды возврата ошибок (расшифровки ErrorLevel)*

Коды возврата ошибок (встроенных команд и других программ)

Порядок получения код возврата
Запускаем приложение, следующей командой проверяем переменную %ErrorLevel%. Есть еще такие варианты написания.
Например,

В языках высокого уровня код возврата можно получить API функцией:

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

либо указав число, которое вернет основная функция,
например main в C++:

Перечень ErrorLevel в этой теме:

Параноя возврата ошибок. Стоит ли проверять каждое действие? Когда останавливаться?
Если. если..если.. Партянка будет длинной.. Например, через 10 лет села батарейка-системная.

cmd код возврата последней команды. tick. cmd код возврата последней команды фото. cmd код возврата последней команды-tick. картинка cmd код возврата последней команды. картинка tick. Проверка IF ERROR LEVEL n срабатывает, если уровень ошибки n или выше. Это, вероятно, потому, что многие программы выражают разную степень ошибки все большими и большими кодах выхода. К примеру, программа diff имеет 3 кода выхода: «0» означает, что файлы одинаковые, «1» — разные, «2» — случилось что-то страшное. Некоторые программы используют код выхода «0» для успеха и все остальное для ошибки.Коды возврата
Код возврата 2. Причина: ошибки работы встроенных средств оболочки. Мой вопрос: какие есть у.

Хорошая тема с простыми примерами, как пользоваться кодами возврата ошибок и сокращенными записями || и &&

Многие родные Microsoft программы, такие как msiexec-установщик, WMIC. используют коды возврата ошибок API-функций.

WGET
Утилита для скачивания с HTTP, HTTPS, FTP файлов и целых сайтов.

0No problems occurred.1Generic error code.2Parse error—for instance, when parsing command-line options, the ‘.wgetrc’ or ‘.netrc’.3File I/O error.4Network failure.5SSL verification failure.6Username/password authentication failure.7Protocol errors.8Server issued an error response.

With the exceptions of 0 and 1, the lower-numbered exit codes take precedence over higher-numbered ones, when multiple types of errors are encountered.

(с примерами и пояснениями для разрешения проблем).

Code 80005000 Object Required
Code 80005001 An unknown ADSI domain object was requested
Code 80005002 An unknown ADSI user object was requested
Code 80005003 An unknown ADSI computer object was requested
Code 8000500D The directory property cannot be found

Code 8009xxxx
Code 80092023 Illegal character in a key name for a certificate

Code 800Axxxx Syntax Errors
In VBScript, there are 53 syntax errors all beginning with 800Axxxx. These errors should be among the easiest to cure because the message often includes the missing punctuation mark or bracket.

Источник

Особенности реализации командного процессора cmd.exe операционных систем WinNT


Или Урок bat-аники 2-ой


Автор: Андрей Дибров
Источник: RSDN Magazine #4-2007

Опубликовано: 15.03.2008
Исправлено: 10.12.2016
Версия текста: 1.6

Предисловие

Желание организовать собранный материал в статью появилось после некоторых исследований работы bat-скриптов и накопления опыта по их составлению в проекте под Microsoft Visual Sudio 2005, интенсивно использующего промежуточные bat-скрипты для взаимодействия непосредственно с некоторыми сторонними консольными утилитами, участвующими в сборке.

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

Статья предусматривает, что читатель уже знаком с написанием bat-скриптов NT (далее просто скриптов), знает о применении команд и умеет пользоваться справкой по встроенным командам и прилагаемым утилитам командного процессора. В статье не рассматриваются сторонние утилиты, а также их проблемы и особенности работы.

ПРИМЕЧАНИЕ

Некоторые проблемы, найденные в скриптах, могут быть связаны с их использованием (запуском) из проекта для Microsoft Visual Studio 2005 (C++), а также, возможно, и других сред, использующих обращения к bat-скриптам.

В конце статьи приведены тексты bat-скриптов и ссылки на некоторые консольные утилиты, использовавшиеся при тестировании примеров.

Тестирование

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

ПРЕДУПРЕЖДЕНИЕ

Здесь и далее все bat-скрипты тестировались в основном только под Windows XP Service Pack 2 (Build 2600.xpsp_sp2_gdr.070227-2254 : Service Pack 2). Возможно, это справедливо и для системы без сервис паков или с предыдущими сервис паками, но это особым образом не проверялось.

Статья не претендует на полный охват всех особенностей командного процессора, могут быть неточности в связи с уже установленными так называемыми фиксами от Microsoft или недосмотром самого автора.

Всё сказанное в статье справедливо для так называемого расширенного режима cmd.exe (установлена переменная CMDEXTVERSION).

Спецсимволы

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

В подавляющем большинстве контекстов часть из них имеет приоритет над всеми остальными символами и командами. Поэтому надо не забывать их вовремя экранировать. К сожалению, в разных контекстах экранировать их следует по-разному. К примеру, внутри скрипта символы

можно экранировать с помощью символа (если не используются ограничивающие кавычки)

Символы «;» и «,» представляют собой альтернативные разделители аргументов для командной строки скриптов и приложений, для их экранирования надо пользоваться только кавычками. Во всех остальных случаях использование и экранирование будет оговорено в соответствующем контексте.

Команда set

Для правильного выполнения тестовых скриптов иногда стоит перезапускать консоль cmd.exe из-за того, что при создании переменных командой set значения созданных переменных остаются в памяти, и результат повторного выполнения скрипта может отличаться от первого выполнения.

Создание переменной

Рассмотрим небольшой пример:

Вывод скрипта “1_1.bat”:

Что здесь может быть неправильно, кроме того, что скрипт выводит не то, что нужно?

Что здесь произошло, можно понять после небольшого исправления.

Вывод скрипта “1_2.bat”:

При использовании команды set слева и справа от равенства нельзя использовать пробелы, иначе командный процессор создаст переменную, название которой заканчивается пробелами, а значение начинается с пробелов и заканчивается последним символом (даже если это пробел). Это одна из причин, по которой при установке переменной не требуется использовать кавычки, т.к. здесь они не являются специальными ограничивающими символами (за исключением использования кавычек вокруг всего выражения A=B ).

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

Вывод скрипта “1_3.bat”:

Удаление переменной


Сброс ERRORLEVEL

Вывод скрипта “1_4.bat”:

Чтобы правильно сбросить код возврата, можно воспользоваться внешней утилитой, которая вернёт заведомо нулевой код возврата, либо встроенной командой, которая предусматривает изменение кода возврата (к примеру, cd ).

Вывод скрипта “1_5.bat”:

Можно также воспользоваться скриптом, который сможет установить переданный ему код возврата (как все скрипты, внутри других скриптов его следует вызывать с применением оператора call ).

Результат работы скрипта “errlvl.bat”:

Условный блок

Из документации следует, что команды условного выполнения имеют в основном две формы. Первая форма – это условие-команда (then-переход), работающее по принципу “одно условие – одна команда”. И вторая форма – условие-блок, работающее по принципу “одно условие – несколько (блок) команд”. В документации это разделение особым образом не оговаривается, но оно есть. И более того, эти две формы могут работать несколько «по-разному». Это становится ясно по двум примерам.

Вывод скрипта “2_1.bat”:

Вывод скрипта “2_2.bat”:

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

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

Условный блок и ERRORLEVEL

Вывод скрипта “3_1.bat”:

Вывод скрипта “3_2.bat”:

Всё дело в скобках!

Вывод скрипта “3_3.bat”:

Таким образом, следует с осторожностью использовать встроенные команды, включающие использование скобок. Необдуманное применение такого оператора может привести к некорректному выполнению скрипта.

Командный процессор cmd.exe


Set и блок

Рассмотрим вызов скрипта через вызов cmd.exe с параметром /c (этот параметр приказывает выполнить строку, переданную в качестве аргумента, и завершить выполнение). Набор параметров cmd.exe и их назначение можно узнать из справки (источники указаны в начале статьи).

Вывод скрипта “4_1.bat”:

Вывод скрипта “4_3.bat”:

Можно устранить этот «эффект» игнорирования кода возврата из скрипта внутри блока простым добавлением call перед названием скрипта.

Вывод скрипта “5_1.bat”:

Или просто не пользоваться “ cmd.exe /c ”.

Вывод скрипта “5_2.bat”:

К тому же, во втором случае после выхода из самого внешнего блока мы также добьёмся «сохранения» переменных, созданных (или изменённых) во «внешнем» скрипте или во внутреннем блоке.

Таким образом, мы решили две проблемы, а именно, сохранили значение переменной MYVALUE1 после выхода из блока и изменили значение ERRORLEVEL также после выхода из блока. Чтобы решить последнюю проблему с изменением переменных только после выхода из самого внешнего блока, достаточно будет удалить все блоки, а если блоки использовались совместно с оператором if, то заменить их соответствующими конструкциями goto + метка (что, несомненно, ухудшит читаемость кода, но избавит от неявного поведения – прим.ред.).

Вывод скрипта “5_3.bat”:

Exit /b %ERRORLEVEL% и блок

Вывод скрипта “6_1.bat”:

Но это происходит из-за того, что ERRORLEVEL на протяжении всего выполнения равен 0, и принимает новое значение только после выхода из самого внешнего блока. Причем это значение не равно 10, так как операция exit /b %ERRORLEVEL% сбрасывает его в 0. Достаточно заменить эту операцию эквивалентной, но приводящей к правильному результату – goto :EOF.

Вывод скрипта “6_2.bat”:

Команда goto


Условный блок

При вызове данного скрипта без параметров, его код будет выводить числа 0, 1, 2, 4 в цикле. Для решения проблемы следует добавить goto в конец первого условного блока.

Вывод скрипта “7_2.bat”:

Команда call


Команда call и блок

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

ПРИМЕЧАНИЕ

Следует сделать уточнение, если вызывается не скрипт, а внешняя утилита, то сценарий выполнения зависит от этой утилиты. Если она была собрана (создана), как консольная, то скрипт ждёт завершения её выполнения. Если как GUI, то не ждёт.

Но суть не в этом, вообще команда call обладает некоторым «магическим» действием. То, что раньше не работало, с её использованием начинает работать.

Вывод скрипта “8_1.bat”

Вывод скрипта “8_2.bat”:

Двойное раскрытие переменной

Данный пункт не относится к проблемным местам в написании скриптов, а скорее является так называемым хинтом.

Вывод скрипта “9_1.bat”:

Вывод скрипта “%9_2%.bat”:

Кстати, в скриптах в качестве имён переменных можно использовать числа и некоторые спецсимволы, а неинициализированные переменные, введённые непосредственно в командную строку консоли cmd.exe, не удаляются, как это происходит в скриптах, т.к. это могут быть обращения к именам файлов. Инициализированные переменные раскрываются всегда.

Поскольку в нашем примере переменная %9_2% не была инициализирована, то, в отличие от скрипта, где бы она была замещена «пустым местом» (или, попросту говоря, удалена), здесь она не была замещена. Что касается текста ошибки, то _2 – это всё, что осталось после раскрытия %9_2% внутри скрипта, где %9 – это встроенная неинициализированная переменная, а % – просто проигнорированный спецсимвол.

Устранить игнорирование двойного раскрытия несложно, достаточно заменить %

Вывод скрипта “%9_3%.bat”:

Получили рекурсивный вызов, как и требовалось. Единственное, что можно было бы здесь рассмотреть ещё, – это раскрытие инициализированных переменных непосредственно в окне консоли.

Вывод скрипта “%9_3%.bat”:

Вывод скрипта “%9_3%.bat”:

Двойное раскрытие переменной и блок

Двойное раскрытие переменной обладает ещё одной особенностью. С его помощью можно обратиться к значению переменной, не ожидая выхода из самого внешнего блока.

Вывод скрипта “10_1.bat”:

ERRORLEVEL равен нулю, так как его сбрасывает вызов операций с помощью команды call.

Его можно также использовать для вызова скриптов и блоков кода внутри блока, и при этом все переменные на момент вызова будут раскрыты, в том числе и те, которые были установлены до вызова call внутри блока.

Вывод скрипта “10_2.bat”:

Результат работы скрипта “expandvar.bat”:

Двойное раскрытие переменной и оператор “!”

Вывод скрипта “11_1.bat”:

Преимущество данного способа заключается в обходе проблемы с раскрытием переменных только после выхода из самого внешнего оператора скобки.

Вывод скрипта “11_2.bat”:

К сожалению, и данный способ содержит недостаток, а именно, “двойной эффект”, и, кроме “включения” оператора “!”, сохраняет все переменные в стек (см. описание команд setlocal/endlocal далее).

Команды setlocal/endlocal


Оператор “!” или оператор “%”?

Фактически, оператор “!” – ни что иное, как оператор “%”, но с меньшим приоритетом.

В следующем примере мы создаём переменную, имя которой состоит из одного символа – “!”. Так как приоритет символа “%” выше, чем “!”, то “%”-переменные раскроются до “!”-переменных.

Вывод скрипта “12_1.bat”:

В дополнение, оператор “!” не экранируем ни самим собой, ни другими конструкциями спецсимволов. В данном случае рекомендуется в качестве замещения экранированию использовать переменную со значением “!”.

Далее показывается, как можно выводить символ “!” при включённом раскрытии “!”-переменных.

Вывод скрипта “12_2.bat”:

Лишние кавычки здесь – детали вызова printargs.exe с параметрами (см. “Вызов с параметрами”).

Восстанавливаем окружение после работы скрипта

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

Результаты работы скрипта “13_2.bat”:

К сожалению, setlocal / endlocal (с параметрами и без) работают только внутри скрипта ( endlocal даже не нужно вызывать явно, после выполнения скрипта, он будет вызван столько же раз, сколько был вызван setlocal в этом же скрипте) и не работают вне его (в окне консоли).

Вызов с параметрами


Вызов внешнего приложения

В общем случае вызов какого-либо приложения с определёнными аргументами не представляет особого интереса, за исключением того, что если параметры берутся в кавычки, то сами кавычки не входят в значения аргументов. В данном примере консольная утилита printargs.exe выводит свои аргументы, взяв при этом каждый из них в кавычки.

Результат выполнения утилиты printargs.exe с аргументами:

Проблема обратного слеша (\)

Результат выполнения утилиты printargs.exe с аргументами:

Чтобы избавиться от этого «эффекта», достаточно добавить ещё один обратный слеш.

Результат выполнения утилиты printargs.exe с аргументами:

Будьте осторожны при использовании встроенных переменных внутри таких аргументов. К примеру, такие переменные как %

p0 всегда содержат завершающий обратный слеш, и будут приводить к тому же «эффекту».

Результат выполнения встроенной команды echo с аргументами:

Call-вызов скрипта и переменные %0-%9

Вывод скрипта “14_1.bat”:

Символы «+» добавлены для более ясной картины происходящего.

Для устранения кавычек, если они имеются, нужно пользоваться “

Вывод скрипта “14_2.bat”:

При этом пробелы справа и слева в значении переменных никуда не пропадают.

Команда if и переменные %0-%9

Порой можно встретить интересные записи условий с использованием переменных-аргументов. Вот некоторые из них.

Или пример из скрипта vcvarsall.bat в Microsoft Visual Studio 2005:

К сожалению, такие формы записи приводят к невозможности передачи параметров с кавычками. Сложности начинаются, когда значения параметров могут содержать пробелы.

Вывод скрипта “15_3.bat”:

Вывод скрипта “15_4.bat”:

Как видно, ничего не изменилось, но стало понятно, какую строчку препроцессор не пропускает. Этого можно избежать, если всегда внутри условий использовать кавычки и “

Вывод скрипта “15_5.bat”:

Исключение составляет сравнение чисел вместо строк. В этом случае использование кавычек может привести к неверному результату.

Вывод скрипта “15_6.bat”:

Вывод скрипта “15_7.bat”:

Команда echo с точкой

Есть одна неприятная особенность, связанная с командой echo. При попытке вывести текст, начинающийся с “/?”, echo вместо предлагаемого текста выводит текст своей справки.

Вывод скрипта “16_1.bat”:

Решение – использовать « echo с точкой».

Вывод скрипта “16_2.bat”:

Кроме того, такое использование удобно в случае вывода аргументов скрипта, т.к. не требует их проверки на существование.

Вывод скрипта “16_3.bat”:

И ещё немного о переменных


Спецсимволы в переменных

Иногда значения переменных могут содержать символы форматирования:

Поэтому некоторые операции над такими значениями могут перестать работать.

Вывод скрипта “17_1.bat”:

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

Вывод скрипта “17_2.bat”:

Но дело может не ограничиваться обычным выводом.

Вывод скрипта “17_3.bat”:

Можно обернуть всё выражение команды set в кавычки.

Вывод скрипта “17_4.bat”:

Или поступить несколько иначе:

Вывод скрипта “17_5.bat”:

Проблемой в данном случае при двойном раскрытии переменной через оператор call будет «авто-экранирование» (дублирование) спецсимвола

Поэтому стоит избегать использования подобных символов в значениях переменных или пользоваться заместителями таких символов в виде других переменных, содержащих эти символы.

Комментарии в скриптах

В основном существует два способа комментировать строки текста внутри скриптов, встроенная команда

ПРИМЕЧАНИЕ

Ошибки могут проявляться в основном в достаточно редких и сложных случаях (вы даже можете не понять, что проблема в комментарии). Проблема решалась простой заменой какого-то одного-двух “::”-комментариев на “ rem ”-комментарии, поэтому рекомендуется не пользоваться “::”-комментариями вообще.

Установка значения переменных из текстовых файлов

Вывод скрипта “18_1.bat”:

В качестве решения помогает переустановка переменной сразу после её чтения из файла.

Вывод скрипта “18_2.bat”:

Установка значения переменных из стандартного вывода

Вывод скрипта “setvarfromstd.bat”:

и проверить появление нового процесса cmd.exe в списке процессов.

Несколько слов о компиляторах

Не существует способа абсолютно переносимо перевести текст bat-файла в exe-программу. И как это не смешно бы звучало, связано это скорее с особенностями самих скриптов (здесь даже речь не идёт о чтении и изменении скрипта самого себя как текстового файла, используя переменную %0 ), а также дизайна как такового, который и мешает самой переносимости.

В Интернете вы можете найти несколько компиляторов:

Есть ли замена cmd.exe?


Заключение

Я постарался привести здесь всё, с чем мне приходилось столкнуться при написании bat-скриптов, но не исключено, что что-то могло быть упущено.

Итак, мы пришли к некоторому набору условий и правил, которые следует выполнять и помнить для написания корректных скриптов, а это:

Приложение


Ключи реестра


Запрет режима командной строки

Для запрета режима командной строки и обработки bat-файлов создайте в этом ключе параметр с именем « DisableCMD », который может принимать значения:

Автовыполнение команд из разделов реестра «AutoRun»

Для текущего сеанса пользователя:

Для всех пользователей:

Запрет расширенного режима командного процессора

Для текущего сеанса пользователя:

Для всех пользователей:

Для запрета расширенного режима командного процессора — cmd.exe создайте в этом ключе параметр с именем « EnableExtensions » и значением «0». Для включения расширенного режима используйте значение «1». Перезапустите консоль, чтобы изменения вступили в силу.

Расширенный режим командного процессора можно также включить или отключить для консольного процесса с помощью параметра /e: или несколько короче: /x – включение, /y – выключение.

Расширенный режим вносит изменения и дополнения в следующие команды:

Отложенное раскрытие переменных среды

Для текущего сеанса пользователя:

Для всех пользователей:

Данный параметр эквивалентен применению команды

на “глобальном” уровне, соответственно, для текущего сеанса пользователя или для всех пользователей.

Отложенное расширение переменных среды по умолчанию не включено. Для включения используйте параметр « DelayedExpansion » со значением «1». Удалите созданный параметр или измените его значение на «0», чтобы вернуть настройки к первоначальному виду. Перезапустите консоль, чтобы изменения вступили в силу.

Также отложенное раскрытие переменных среды можно включить или отключить для консольного процесса cmd.exe с помощью параметра /v: .

Автозавершение имён файлов и папок

Для текущего сеанса пользователя:

Для всех пользователей:

Также автозавершение имён файлов и папок можно включить или отключить для консольного процесса cmd.exe с помощью параметра /f: .

Внешние утилиты и скрипты

В этом разделе описаны утилиты и скрипты, прилагаемые к статье. Некоторые представленные здесь скрипты могут вызывать другие, поэтому следует рассматривать их вместе.

ПРИМЕЧАНИЕ

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

errlvl.exe/errlvl.bat


printargs.exe

Выводит на консоль свои входные аргументы с добавлением ограничивающих кавычек.

unset.bat

Безопасно удаляет переменную.

printfile.bat

Печатает текстовой файл на экран.

Того же эффекта можно добиться и с помощью команды type :

appendvar.bat

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

expandvar.bat

Раскрывает строку, переданную вторым аргументом, и сохраняет значение в переменную, имя которой передано первым аргументом. Скрипт восстанавливает код возврата, сбрасываемый оператором call внутри скрипта.

setvarfromstd.bat

Получает в качестве параметров команду и ее аргументы, выполняет команду, передав ей эти аргументы, и помещает результат в переменную STDOUT_VALUE.

joinvars.bat

Объединяет все строчки из входного текстового файла в одну строчку (используя как разделитель точку с запятой), и присваивает её переменной.

Результат работы скрипта “joinvars.bat”:

Результат работы скрипта “joinvars.bat”:

splitvars.bat

Разбивает все строчки из входного файла/литерала, объединённых через точку с запятой, на несколько строчек и последовательно выводит их.

Результат работы скрипта “splitvars.bat”:

iffexist.bat

Проверяет существование файла в каталогах из списка который может быть задан текстовым файлом или строкой где отдельные значения разделяются точкой с запятой (как в переменной PATH ) или переменной (например, переменной PATH ). Устанавливает переменную FOUND_PATH и возвращает 0 в случае существования файла по одному из путей в списке и 1 – в случае его отсутствия.

Источник

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

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