Среда командной оболочки Cmd.exe определяется переменными, задающими поведение командной оболочки и операционной системы. Имеется возможность определить поведение среды командной оболочки или среды всей операционной системы с помощью двух типов переменных среды: системных и локальных. Системные переменные среды определяют поведение глобальной среды операционной системы. Локальные переменные среды определяют поведение среды в данном экземпляре Cmd.exe.
Системные переменные среды заданы заранее в операционной системе и доступны для всех процессов Windows XP. Только пользователи с привилегиями администратора могут изменять эти переменные. Эти переменные наиболее часто используются в сценариях входа в систему.
Локальные переменные среды доступны, только когда пользователь, для которого они были созданы, вошел в систему. Локальные переменные из куста HKEY_CURRENT_USER подходят только для текущего пользователя, но определяют поведение глобальной среды операционной системы.
В следующем списке представлены различные типы переменных в порядке убывания приоритета.
- Встроенные системные переменные
- Системные переменные куста HKEY_LOCAL_MACHINE
- Локальные переменные куста HKEY_CURRENT_USER
- Все переменные среды и пути указаны в файле Autoexec.bat.
- Все переменные среды и пути указаны в сценарии входа в систему (если он имеется).
- Переменные, используемые интерактивно в сценарии или пакетном файле
В командной оболочке каждый экземпляр Cmd.exe наследует среду своего родительского приложения. Поэтому можно изменять переменные в новой среде Cmd.exe, что не повлияет на среду родительского приложения.
В следующей таблице приведен список системных и локальных переменных среды для Windows XP.
Переменная | Описание |
|
---|---|---|
%ALLUSERSPROFILE% | Локальная | Возвращает размещение профиля «All Users». |
Локальная | Возвращает используемое по умолчанию размещение данных приложений. |
|
Локальная | Возвращает путь к текущей папке. |
|
Локальная | Возвращает строку команд, с помощью которой был запущен данный экземпляр Cmd.exe. |
|
Системная | Возвращает номер версии текущих расширений обработчика команд. |
|
Системная | Возвращает имя компьютера. |
|
Системная | Возвращает путь к исполняемой командной оболочке. |
|
Системная | Возвращает текущие данные. Использует тот же формат, что и команда date /t . Создается командой Cmd.exe. |
|
Системная | Возвращает код ошибки последней использовавшейся команды. Значение, не равное нуля, обычно указывает на наличие ошибки. |
|
Системная | Возвращает имя диска локальной рабочей станции, связанного с основным каталогом пользователя. Задается на основании расположения основного каталога. Основной каталог пользователя указывается в оснастке «Локальные пользователи и группы». |
|
Системная | Возвращает полный путь к основному каталогу пользователя. Задается на основании расположения основного каталога. Основной каталог пользователя указывается в оснастке «Локальные пользователи и группы». |
|
Системная | Возвращает сетевой путь к общему основному каталогу пользователя. Задается на основании расположения основного каталога. Основной каталог пользователя указывается в оснастке «Локальные пользователи и группы». |
|
Локальная | Возвращает имя контроллера домена, который проверял подлинность текущей сессии. |
|
%NUMBER_OF_PROCESSORS% | Системная | Задает количество процессоров, установленных на компьютере. |
Системная | Возвращает имя операционной системы. При использовании Windows 2000 имя операционной системы отображается как Windows_NT. |
|
Системная | Указывает путь поиска для исполняемых файлов. |
|
Системная | Возвращает список расширений файлов, которые рассматриваются операционной системой как исполняемые. |
|
%PROCESSOR_ARCHITECTURE% | Системная | Возвращает архитектуру процессора. Значения: x86, IA64. |
%PROCESSOR_IDENTFIER% | Системная | Возвращает описание процессора. |
%PROCESSOR_LEVEL% | Системная | Возвращает номер модели процессора, установленного на компьютере. |
%PROCESSOR_REVISION% | Системная | Возвращает номер модификации процессора. |
Локальная | Возвращает параметры командной строки для текущего интерпретатора. Создается командой Cmd.exe. |
|
Системная | Возвращает произвольное десятичное число от 0 до 32767. Создается командой Cmd.exe. |
|
Системная | Возвращает имя диска, содержащего корневой каталог Windows XP (т. е. системный каталог). |
|
Системная | Возвращает размещение системного каталога Windows XP. |
|
Системная и пользовательская | Возвращает временные папки, по умолчанию используемые приложениями, которые доступны пользователям, выполнившим вход в систему. Некоторые приложения требуют переменную TEMP, другие — переменную TMP. |
|
Системная | Возвращает текущее время. Использует тот же формат, что и команда time /t . Создается командой Cmd.exe. |
|
Локальная | Возвращает имя домена, содержащего список учетных записей пользователей. |
|
Локальная | Возвращает имя пользователя, выполнившего вход в систему. |
|
Локальная | Возвращает размещение профиля для текущего пользователя. |
|
Системная | Возвращает размещение каталога операционной системы. |
Объявление собственных переменных является неотъемлемой часть практически любого языка программирования, так в языке vbscript они объявляются с помощью ключевого слова dim , а в jscript – используется ключевое слово var .
Переменные командной строки Windows представляют немного другой характер, тут нельзя объявить группу переменных cmd, или же сразу присвоить значения нескольким переменным в командной строке. Давайте посмотрим на следующие строчки кода:
echo % Var3% echo % VAR3% echo % vAr3% |
Стоит учитывать один момент, запись
set var1 =100 |
set var1 = 100 |
это не одно и тоже, то есть, в первом случае мы создаем cmd переменную "var1", а во втором – "var1 ". С присвоением значений аналогичная ситуация, так что обращайте внимание на пробел!!!
Видим, что бы вывести значение переменной с помощью функции Echo , мы заключаем ее в символ "%", для set – просто прописываем ее имя, так же стоит учитывать, что всем переменным присваивается строковой тип.
Если вы запустите на выполнение команду cmd set, которая выводит список всех переменных и их значений в текущем сеансе, то увидите, что там будут присутствовать и только что созданные cmd переменные и . Мы сможем обращаться к ним на протяжение всего сеанса работы.
Что бы очистить переменные в командной строке Windows от их содержимого, нужно просто присвоить пустое значение:
просто выведет строчку %Var3%, а команда
В данном примере мы экранировали символы & и ^, тем самым присвоив фразы:
"100 & 3 = 5"
"100 ^3"
Стоит обратить внимание, что если мы попытаемся вывести значения данных переменных с помощью функции cmd set, то проблем не возникнет, но если будет использовать функцию echo, то получим совсем не тот результат, что ожидали. Так, при попытке выполнить следующую команду:
Теперь при выполнении кода:
echo % var4% echo % var5% |
все пройдет успешно.
Понятно, что переменные cmd, созданные в текущем окне командной строки недоступна для других процессов, но, есть возможность задать ограничения еще большие.
Что бы задать локальную область видимости, используется блок SETLOCAL … ENDLOCAL . Все cmd переменные командной строки Windows, объявленные в середине данного блока не будут видны за его пределами. Откройте редактор (я использую редактор Notepad++ , так как он сразу подсвечивает код), и пропишите в нем следующие строчки кода:
Видим, что вначале мы объявили var1 и присвоили ей значение 0, далее мы снова объявили переменную с аналогичным именем, но уже в блоке SETLOCAL … ENDLOCAL . В сценарии происходит вывод значения как локальной, так и глобальной var1. Я специально использовал латинские знаки, что бы у вас в случае чего не выводились крякозябры.
Среда командной оболочки cmd.exe определяется переменными, которые задают поведение командной оболочки и операционной системы.
Есть возможность определить поведение среды командной оболочки или среды всей операционной системы с помощью двух типов переменных среды: системных и локальных.
Системные переменные среды определяют поведение глобальной среды операционной системы, а локальные переменные среды определяют поведение среды в данном экземпляре cmd.exe.
Системные переменные среды заданы поумодчанию в операционной системе и доступны для всех процессов Windows, и пользователи с привилегиями администратора могут изменять эти переменные. Эти переменные наиболее часто используются в сценариях входа в систему.
Локальные переменные среды доступны когда пользователь, для которого они были созданы, вошел в систему. Локальные переменные из куста реестра HKEY_CURRENT_USER подходят только для текущего пользователя, но определяют поведение глобальной среды операционной системы.
Список типов переменных в порядке убывания приоритета.
- Встроенные системные переменные
- Системные переменные куста реестра HKEY_LOCAL_MACHINE
- Локальные переменные куста реестра HKEY_CURRENT_USER
- Все переменные среды и пути указаны в файле Autoexec.bat.
- Все переменные среды и пути указаны в сценарии входа в систему (если он имеется).
- Переменные, используемые интерактивно в сценарии или пакетном файле
В командной оболочке каждый экземпляр cmd.exe наследует среду своего родительского приложения и соответственно можно изменять переменные в новой среде сmd.exe, что никак не повлияет на среду родительского приложения.
Вот список системных и локальных переменных среды для Windows XP.
Переменная |
Описание |
|
---|---|---|
%ALLUSERSPROFILE% |
Локальная |
Возвращает размещение профиля «All Users». |
Локальная |
Возвращает используемое по умолчанию размещение данных приложений. |
|
Локальная |
Возвращает путь к текущей папке. |
|
Локальная |
Возвращает строку команд, с помощью которой был запущен данный экземпляр Cmd.exe. |
|
Системная |
Возвращает номер версии текущих расширений обработчика команд. |
|
Системная |
Возвращает имя компьютера. |
|
Системная |
Возвращает путь к исполняемой командной оболочке. |
|
Системная |
Возвращает текущие данные. Использует тот же формат, что и команда date /t . Создается командой Cmd.exe. |
|
Системная |
Возвращает код ошибки последней использовавшейся команды. Значение, не равное нуля, обычно указывает на наличие ошибки. |
|
Системная |
Возвращает имя диска локальной рабочей станции, связанного с основным каталогом пользователя. Задается на основании расположения основного каталога. Основной каталог пользователя указывается в оснастке «Локальные пользователи и группы». |
|
Системная |
Возвращает полный путь к основному каталогу пользователя. Задается на основании расположения основного каталога. Основной каталог пользователя указывается в оснастке «Локальные пользователи и группы». |
|
Системная |
Возвращает сетевой путь к общему основному каталогу пользователя. Задается на основании расположения основного каталога. Основной каталог пользователя указывается в оснастке «Локальные пользователи и группы». |
|
Локальная |
Возвращает имя контроллера домена, который проверял подлинность текущей сессии. |
|
%NUMBER_OF_PROCESSORS% |
Системная |
Задает количество процессоров, установленных на компьютере. |
Системная |
Возвращает имя операционной системы. При использовании Windows 2000 имя операционной системы отображается как Windows_NT. |
|
Системная |
Указывает путь поиска для исполняемых файлов. |
|
Системная |
Возвращает список расширений файлов, которые рассматриваются операционной системой как исполняемые. |
|
%PROCESSOR_ARCHITECTURE% |
Системная |
Возвращает архитектуру процессора. Значения: x86, IA64. |
%PROCESSOR_IDENTFIER% |
Системная |
Возвращает описание процессора. |
%PROCESSOR_LEVEL% |
Системная |
Возвращает номер модели процессора, установленного на компьютере. |
%PROCESSOR_REVISION% |
Системная |
Возвращает номер модификации процессора. |
Локальная |
Возвращает параметры командной строки для текущего интерпретатора. Создается командой Cmd.exe. |
|
Системная |
Возвращает произвольное десятичное число от 0 до 32767. Создается командой Cmd.exe. |
|
Системная |
Возвращает имя диска, содержащего корневой каталог Windows XP (т. е. системный каталог). |
|
Системная |
Возвращает размещение системного каталога Windows XP. |
|
Системная и пользовательская |
Возвращает временные папки, по умолчанию используемые приложениями, которые доступны пользователям, выполнившим вход в систему. Некоторые приложения требуют переменную TEMP, другие - переменную TMP. |
|
Системная |
Возвращает текущее время. Использует тот же формат, что и команда time /t . Создается командой Cmd.exe. |
|
Локальная |
Возвращает имя домена, содержащего список учетных записей пользователей. |
|
Локальная |
Возвращает имя пользователя, выполнившего вход в систему. |
|
Локальная |
Возвращает размещение профиля для текущего пользователя. |
|
Системная |
Возвращает размещение каталога операционной системы. |
Иногда требуется сформировать переменную даты и времени в cmd / bat скриптах windows так, как нужно нам, а не так, как нам отдаёт операционная система.
Например чтоб добавить эти данные в log файл, для фиксации времени или даты события, создать файл с именем, в котором должны фигурировать данные даты или времени (день, месяц, год, час, минуты, скунды, миллисекунды.) Да мало-ли, какие у нас задачи... Подключаем нашу фантазию :)
В следующем примере мы видим разбиение переменных по нужным нам шаблонам.
h- час 2 знака (то есть час будет выдаваться в следующем виде - 01, 02, ..., 09, ... , 12, ... 24)
m - минуты 2 знака
s - секунжы 2 знака
ms - миллисекунды 2 знака, почему-то от 0 до 99
dd - день 2 знака
mm - месяц 2 знака
yyyy - год 4 знака
Пример использования переменных %DATE% и %TIME% в скриптах cmd / bat Windows:
@echo off
set h=%TIME:~0,2%
set m=%TIME:~3,2%
set s=%TIME:~6,2%
set ms=%TIME:~9,2%
set curtime=%h%:%m%:%s%:%ms%
set dd=%DATE:~0,2%
set mm=%DATE:~3,2%
set yyyy=%DATE:~6,4%
set curdate=%dd%-%mm%-%yyyy%
set curdatetime=%curdate% %curtime%
echo Текущее время - %curdatetime%
В некоторых версиях Windows формат выдачи даты и времени другой, поэтому данный скрипт может работать совсем так как нам нужно.
По идее, подобным способом можно брать части любых переменных, суть в том что формат здесь такой:
Первая цифра после:~ - это номер символа, с которого мы начинаем брать значение, вторая цифра это сколько символов захватывать.
Таким образом получается что мы можем взять для своих нужд любую часть, любой доступной нам переменной среды Windows.
Мне известны следующие переменные, значения которых мы можем получить:
ALLUSERSPROFILE | Возвращает размещение профиля «All Users». |
APPDATA | Возвращает используемое по умолчанию размещение данных приложений. |
CD | Указывает путь текущей папки. Идентична команде CD без аргументов. |
CMDCMDLINE | точная команда использованная для запуска текущего cmd.exe. |
CMDEXTVERSION | версия текущего Command Processor Extensions. |
CommonProgramFiles | Расположение каталога "Common Files" (обычно %ProgramFiles%\Common Files) |
COMPUTERNAME | имя компьютера |
COMSPEC | путь до исполняемого файла shell |
DATE | Возвращает текущую дату. Использует тот же формат, что и команда date /t. Создается командой Cmd.exe. |
ERRORLEVEL | Возвращает код ошибки последней использовавшейся команды. Значение, не равное нулю, обычно указывает на наличие ошибки. |
HOMEDRIVE | Возвращает имя диска локальной рабочей станции, связанного с основным каталогом пользователя. Задается на основании расположения основного каталога. Основной каталог пользователя указывается в оснастке «Локальные пользователи и группы». |
HOMEPATH | Возвращает полный путь к основному каталогу пользователя. Задается на основании расположения основного каталога. Основной каталог пользователя указывается в оснастке «Локальные пользователи и группы». |
HOMESHARE | Возвращает сетевой путь к общему основному каталогу пользователя. Задается на основании расположения основного каталога. Основной каталог пользователя указывается в оснастке «Локальные пользователи и группы». |
LOGONSERVER | имя контроллера домена, использовавшегося для авторизации текущего пользователя |
NUMBER_OF_PROCESSORS | количество процессоров в системе |
OS | название операционной системы. Windows XP и Windows 2000 отображаются как Windows_NT. |
PATH | Указывает путь поиска для исполняемых файлов. |
PATHEXT | Возвращает список расширений файлов, которые рассматриваются операционной системой как исполняемые. |
PROCESSOR_ARCHITECTURE | архитектура процессора |
PROCESSOR_IDENTIFIER | описание процессора |
PROCESSOR_LEVEL | номер модели процессора |
PROCESSOR_REVISION | ревизия процессора |
PROGRAMFILES | путь к папке Program Files |
PROMPT | Возвращает параметры командной строки для текущего интерпретатора. Создается командой Cmd.exe. |
RANDOM | случайное десятичное число от 0 до 32767. Генерируется Cmd.exe |
SESSIONNAME | Тип сессии. Значение по умолчанию "Console" |
SYSTEMDRIVE | диск на котором расположена корневая папка Windows |
SYSTEMROOT | путь к корневой папке Windows |
TEMP or TMP | Возвращает временные папки, по умолчанию используемые приложениями, которые доступны пользователям, выполнившим вход в систему. Некоторые приложения требуют переменную TEMP, другие — переменную TMP. Потенциально TEMP и TMP могут указывать на разные каталоги, но обычно - совпадают. |
TIME | Возвращает текущее время. Использует тот же формат, что и команда time /t. Создается командой Cmd.exe. |
USERDOMAIN | имя домена, которому принадлежит текущий пользователь |
USERNAME | имя текущего пользователя |
USERPROFILE | путь к профайлу текущего пользователя |
WINDIR | директория в которую установлена Windows |
В этой статье:
- Определение переменных
- Переменные командной строки (параметры вызова bat-файла)
- Оператор условия IF
- Функции
- Использование возвращаемых значений (обработка кода завершения программы)
Определение переменных
SET <Имяпеременной>=<Значениепеременной>
Оператор SET представляет собой расширение возможностей работы с параметрами в операционной системе. Он задает переменную, значение которой подставляется вместо ее имени при любом использовании этого имени между знаками процента. Так, если задано (переменная, которую требуют многие игры, использующие звуковую карту компьютера):
SET BLASTER=A220 I5 D1 P330
то при использовании в пакетном файле следующей конструкции:
ECHO %BLASTER%
на экран будет выведено "A220 I5 D1 P330". Переменные, определенные с помощью оператора SET называются переменными окружения среды (environment) и являются видимыми после выполнения до перезапуска DOS (если не изменять ее вручную в памяти). То есть, ее можно использовать из одного пакетного файла или программы после задания в другом. Наиболее известной является переменная PATH, представляющая собой набор путей для быстрого поиска файлов. Она задается в файле autoexec.bat.
Переменные командной строки
(параметры вызова bat-файла)
%<цифра 0-9>
Как и в любом языке, в языке пакетных файлов возможно использование переменных, полученных в качестве параметров bat-файла.
Всего может быть 10 одновременно существующих независимых переменных. Для написания сложных программ это довольно мало, хотя для обычной работы часто хватает и 3-4. Значение переменной равно значению соответствующего параметра из командной строки. Переменная %0 будет содержать имя.bat-файла и, если вы указали, путь к нему. То есть, если вы запустили файл abc.bat со следующими параметрами:
abc.bat a bc def
то переменная %0 будет содержать значение abc.bat , %1 будет содержать значение a, %2 будет содержать bc , а %3 - def . Это свойство широко используется для создания универсальных пакетных файлов при работе с повторяющимися операциями.
Чтобы получить более чем 10 переменных из командной строки, можно воспользоваться командой SHIFT .
Команда SHIFT позволяет использовать число параметров командной строки далее 10. Однако, при этом теряются соответственно более ранние параметры. Иными словами, команда SHIFT сдвигает все значения переменных на один шаг влево. То есть, переменная %0 будет содержать значение, содержавшееся до этого в переменной %1 , а переменная %1 - значение переменной %2 до сдвига. Однако, данная операция является необратимой, то есть, невозможно сдвинуть переменные обратно.
Оператор условия IF
К счастью, командный интерпретатор cmd.exe современных ОС Windows 2000 и старше поддерживает блоки команд в конструкциях ветвления, что устраняет необходимость применения IF с метками. Блоки команд заключаются в круглые скобки. Выглядит это так (имитируя C/C++ indentation style):
if condition (
Rem Команды ветки ‘then’
Rem ...
) else (
Rem Команды ветки ‘else’
Rem ...
Конкретный пример использования:
@echo off
set BUILDMODE=%1
if "%BUILDMODE%" == "" (
Echo FAIL: Аргумент является обязательным ^(--debug, --release^)
Exit /b 1
rem Удаляем из аргумента все дефисы для упрощения обработки
set BUILDMODE=%BUILDMODE:-=%
if "%BUILDMODE%" == "debug" (
Set CCFLAGS=/Od /MDd /Z7
) else (
Set CCFLAGS=/O2 /MD
На мой взгляд, с этим уже вполне можно жить. Но, как всегда, жизнь не так проста, как кажется. Есть одна проблема. Переменные, использующиеся в блоках then и else, раскрываются перед началом выполнения этих блоков, а не в процессе выполнения. В приведенном примере это не вызывает никаких проблем, однако в следующем вызовет:
if "%BUILDMODE%" == "debug" (
Echo INFO: Устанавливаем debug-режим окружения
Set OPTFLAGS=/Od
Set CCFLAGS=%OPTFLAGS% /MDd /Z7
) else (
Echo INFO: Устанавливаем release-режим окружения
Set OPTFLAGS=/O2
Set CCFLAGS=%OPTFLAGS% /MD
Загвоздка в том, что в обоих блоках подстановка переменной OPTFLAGS произойдет до того, как она будет изменена в процессе выполнения этого блока. Соответственно, в CCFLAGS будет подставлено то значение, которое OPTFLAGS имела на момент начала выполнения данного if-блока.
Решается эта проблема путем использования отложенного раскрытия переменных. Переменные, заключенные в !…! вместо %…% , будут раскрыты в их значения только в момент непосредственного использования. Данный режим по умолчанию отключен. Включить его можно либо использованием ключа /V:ON при вызове cmd.exe , либо использованием команды:
в тексте самого bat-файла. Второй способ мне представляется более удобным – не очень здорово требовать от кого-то запуска твоего сценария с определенным параметром.
С учетом сказанного предыдущий «неправильный» пример может быть исправлен так:
setlocal enabledelayedexpansion
if "%BUILDMODE%" == "debug" (
Echo INFO: Setting up debug mode environment
Set OPTFLAGS=/Od
Set CCFLAGS=!OPTFLAGS! /MDd /Z7
) else (
Echo INFO: Setting up release mode environment
Set OPTFLAGS=/O2
Set CCFLAGS=!OPTFLAGS! /MD
Вот теперь это почти полноценный if-then-else блок. Почти, потому что если в одной из команд echo у вас встретится закрывающая круглая скобка, то вам необходимо заэкранировать ее символом ^, иначе синтаксический анализатор путается…
Но в любом случае, это гораздо лучше безумного количества меток и переходов.
Функции
А можно создать в bat-файле функцию? Да, можно. Более того, иногда даже нужно. Правда, функциями это можно назвать условно.
Есть особый синтаксис команды call , который позволяет перейти на метку в этом же bat-файле с запоминанием места, откуда был произведен этот вызов:
call:метка аргументы
Возврат из функции производится командой:
exit /b [опциональный код возврата]
Ключ /b здесь очень важен: без него будет произведен выход не из функции, а из сценария вообще.
За подробностями наберите в командной строке:
call /?
exit /?
Что интересно, команда call с таким синтаксисом поддерживает рекурсивные вызовы с автоматическим созданием нового фрейма для переменных аргументов %0-%9. Иногда это может быть полезным. Вот классический пример рекурсивного подсчета факториала на командном языке:
@echo off
call:factorial %1
echo %RESULT%
exit
rem Функция для подсчета значения факториала
rem Вход:
rem %1 Число, для которого необходимо подсчитать факториал
rem Выход:
rem %RESULT% Значение факториала
:factorial
if %1 == 0 (
Set RESULT=1
Exit /b
if %1 == 1 (
Set RESULT=1
Exit /b
set /a PARAM=%1 - 1
call:factorial %PARAM%
set /a RESULT=%1 * %RESULT%
exit /b
Пример работы:
> factorial.bat 10
3628800
Использование возвращаемых значений
(обработка кода завершения программы)
Любая программа при завершении своей работы возвращает операционной системе код своего завершения. Принято при успешном завершении возвращать ноль, иначе - код ошибки. Иногда, или, вернее, часто, программа "сознательно" возвращает ненулевое значение для того, чтобы в пакетном файле можно было "узнать" некоторые подробности ее работы. Например, программа возвращает код нажатой клавиши, а.bat-файл по нему выполняет различные действия.
Каким же образом пакетный файл может узнать код завершения выполненной программы? Для этого предусмотрено ключевая переменная ERRORLEVEL .
Пример пакетного файла с errorlevel"ами:
@ECHO OFF
REM Запускаем программу prg1.exe
PRG1.EXE
REM Анализ кода завершения
IF ERRORLEVEL 2 GOTO FILENOTFOUND
IF ERRORLEVEL 1 GOTO WRITEERROR
IF ERRORLEVEL 0 GOTO EXITOK
GOTO ONEXIT
:FILENOTFOUND
ECHO Ошибка! Файл не найден!
GOTO ONEXIT
:WRITEERROR
ECHO Ошибка записи!
GOTO ONEXIT
:EXITOK
ECHO Программа завершена благополучно.
GOTO ONEXIT
:ONEXIT
Обратите внимание - анализ кода завершения начинается не с нуля, а с максимально возможного значения. Дело в том, что подобная проверка означает: "если errorlevel больше или равен значению, то...". То есть, если мы будем проверять, начиная с нуля, любое значение будет истинным на первой же строке, что неверно.
Это самая распространенная ошибка в подобного рода программах.