Страница Ивана Рощина > Статьи >

© Иван Рощин, Москва

ZXNet: 500:95/462.53
E-mail: bestview@mtu-net.ru
WWW: http://www.ivr.da.ru

Автоконтроль порядка запуска bat-файлов

Мир ПК» 4/2007)

Рассмотрим такую ситуацию. В некотором каталоге есть два bat-файла (назовём их 1.bat и 2.bat), с помощью которых обрабатываются некие данные. Обработка происходит так: сначала пользователь запускает файл 1.bat, после его выполнения производит некоторые действия с данными, а затем запускает 2.bat (то есть 1.bat и 2.bat не могут быть объединены в один bat-файл). Порядок запуска bat-файлов должен быть именно таким, а если вместо 1.bat пользователь случайно запустит 2.bat или наоборот, то в результате неправильного порядка обработки данные будут испорчены.

Случайно запустить не тот файл вполне возможно: всё-таки человеку свойственно ошибаться — промахнулся курсором, и всё. Но терять данные в таком случае не хотелось бы. Как же быть? Очевидно, имеет смысл возложить на компьютер контроль за правильным порядком запуска этих файлов — пусть при ошибке выдаётся соответствующее сообщение, предотвращая тем самым порчу данных. Как же это сделать?

Идея весьма проста. Изменим bat-файлы так, чтобы при выполнении 1.bat создавался (скажем, в текущем каталоге) специальный временный файл (его содержимое не имеет значения), а при выполнении 2.bat этот файл удалялся. Назовём этот временный файл, скажем, after_1.$$$ (after значит «после», «1» — имя bat-файла, создающего данный файл, ну а расширение $$$ выбрано как свойственное временным файлам). Также пусть при запуске 1.bat сначала проверяется, чтобы файла after_1.$$$ не существовало, а при запуске 2.bat — наоборот, чтобы он существовал. И если проверяемое условие не выполняется, пусть выдаётся сообщение «Неправильный порядок запуска файлов!» и работа с bat-файлом завершается.

Для реализации изложенного в начало файла 1.bat добавляем следующие строки:

@if not exist after_1.$$$ goto order_ok
@echo Неправильный порядок запуска файлов!
@goto end
:order_ok
@echo >after_1.$$$

В начало файла 2.bat добавляем:

@if exist after_1.$$$ goto order_ok
@echo Неправильный порядок запуска файлов!
@goto end
:order_ok
@del after_1.$$$

И в конец обоих файлов добавляем метку end:

:end

Разумеется, если в редактируемом bat-файле уже используются метки с такими же именами, как добавляемые (order_ok, end), то в добавляемых строках нужно выбрать другие имена меток. А если оказалось, что метка end и так уже стоит в конце bat-файла, то добавлять её не нужно.

Также отмечу, что сообщение «Неправильный порядок запуска файлов!» должно быть записано в кодировке DOS, т.к. именно в ней происходит вывод на экран при выполнении bat-файла.

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

Итак, эта задача решена, а теперь обобщим её на случай произвольного числа bat-файлов. Пусть имеется n файлов: 1.bat, 2.bat, …, n.bat, которые должны запускаться именно в таком порядке. Тогда изменим файлы так, чтобы при выполнении файла 1.bat создавался файл after_1.$$$, при выполнении 2.bat — after_1.$$$ удалялся и создавался after_2.$$$, при выполнении 3.bat — удалялся after_2.$$$ и создавался after_3.$$$, …, при выполнении n.bat — удалялся after_n-1.$$$. Соответственно делаем следующие проверки в bat-файлах: в 1.bat проверяется, чтобы не существовало ни одного из файлов after_1.$$$, after_2.$$$, …, after_n-1.$$$; в 2.bat проверяется, чтобы существовал файл after_1.$$$; в 3.bat проверяется, чтобы существовал файл after_2.$$$; и т.д. Если проверяемое условие не выполняется, выдаётся сообщение «Неправильный порядок запуска файлов!» и выполнение bat-файла завершается.

Ниже показано, какие строки нужно добавить в bat-файлы для реализации изложенного при n=3.

В начало файла 1.bat добавляем:

@if exist after_1.$$$ goto order_err
@if exist after_2.$$$ goto order_err
@goto order_ok
:order_err
@echo Нарушен порядок запуска файлов!
@goto end
:order_ok
@echo >after_1.$$$

В начало файла 2.bat добавляем:

@if exist after_1.$$$ goto order_ok
@echo Нарушен порядок запуска файлов!
@goto end
:order_ok
@del after_1.$$$
@echo >after_2.$$$

В начало файла 3.bat добавляем:

@if exist after_2.$$$ goto order_ok
@echo Нарушен порядок запуска файлов!
@goto end
:order_ok
@del after_2.$$$

В конец каждого из этих трёх файлов добавляем, как и в прошлом случае, метку end.

Кстати, обратите внимание на первые строки, добавляемые в начало файла 1.bat:

@if exist after_1.$$$ goto order_err
@if exist after_2.$$$ goto order_err
@goto order_ok
:order_err

Тут можно было бы записать короче (вторую и третью строку заменить одной):

@if exist after_1.$$$ goto order_err
@if not exist after_2.$$$ goto order_ok
:order_err

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

@if exist after_1.$$$ goto order_err
@if exist after_2.$$$ goto order_err
@if exist after_3.$$$ goto order_err    <-- добавленная строка
@goto order_ok
:order_err

А в более коротком варианте пришлось бы добавить одну строку и отредактировать другую:

@if exist after_1.$$$ goto order_err
@if exist after_2.$$$ goto order_err    <-- добавленная строка
@if not exist after_3.$$$ goto order_ok <-- отредактированная строка
:order_err

То есть редактирование в этом случае оказалось бы более сложным.

Автоконтроль может быть применён и при нелинейном порядке запуска файлов (когда есть ветвления и/или циклы). При этом, однако, не обеспечивается распознавание всех ошибок. Рассмотрим пример:

Схема

Здесь после файла a.bat может быть запущен либо b.bat, либо c.bat, а группа из файлов c.bat и d.bat может быть выполнена многократно. Какие же действия должны производиться в каждом из этих файлов для автоконтроля?

Смотрим на схему. Так как после выполнения b.bat или e.bat обработка данных заканчивается, то при их выполнении временные файлы создавать не нужно. Остаются a.bat, c.bat и d.bat — вот при их выполнении и будут создаваться временные файлы, назовём их соответственно after_a.$$$, after_c.$$$ и after_d.$$$.

Временный файл должен существовать лишь в промежутке между запуском того bat-файла, в котором он создаётся, и запуском следующего bat-файла (в котором он, следовательно, должен уничтожаться). Исходя из этого в b.bat должен уничтожаться файл after_a.$$$; в c.bat — либо after_a.$$$, либо after_d.$$$ (смотря какой из них существует); в d.bat — after_c.$$$, в e.bat — after_d.$$$.

Теперь определим, какие в каком файле должны производиться проверки. При запуске a.bat, то есть при начале обработки данных, не должно быть ни after_a.$$$, ни after_c.$$$, ни after_d.$$$. Файл b.bat должен быть запущен только после a.bat — значит, при его запуске должен существовать файл after_a.$$$. Файл c.bat должен быть запущен либо после a.bat, либо после d.bat — значит, при его запуске должен существовать либо файл after_a.$$$, либо after_d.$$$. Файл d.bat должен быть запущен только после c.bat — значит, при его запуске должен существовать файл after_c.$$$. Файл e.bat должен быть запущен только после d.bat — значит, при его запуске должен существовать файл after_d.$$$.

Ниже показано, какие строки нужно добавить в bat-файлы для реализации изложенного.

В начало файла a.bat добавляем:

@if exist after_a.$$$ goto order_err
@if exist after_c.$$$ goto order_err
@if exist after_d.$$$ goto order_err
@goto order_ok
:order_err
@echo Нарушен порядок запуска файлов!
@goto end
:order_ok
@echo >after_a.$$$

В начало файла b.bat добавляем:

@if exist after_a.$$$ goto order_ok
@echo Нарушен порядок запуска файлов!
@goto end
:order_ok
@del after_a.$$$

В начало файла c.bat добавляем:

@if exist after_a.$$$ goto order_ok
@if exist after_d.$$$ goto order_ok
@echo Нарушен порядок запуска файлов!
@goto end
:order_ok
@if exist after_a.$$$ del after_a.$$$
@if exist after_d.$$$ del after_d.$$$
@echo >after_c.$$$

В начало файла d.bat добавляем:

@if exist after_c.$$$ goto order_ok
@echo Нарушен порядок запуска файлов!
@goto end
:order_ok
@del after_c.$$$
@echo >after_d.$$$

В начало файла e.bat добавляем:

@if exist after_d.$$$ goto order_ok
@echo Нарушен порядок запуска файлов!
@goto end
:order_ok
@del after_d.$$$

И, как обычно, в конец каждого из этих файлов добавляем метку end.

В данном примере ошибка, когда после запуска a.bat запускается b.bat вместо c.bat или наоборот, не может быть распознана средствами автоконтроля, ведь оба варианта считаются допустимыми. Аналогично не может быть распознана ошибка, когда после запуска d.bat запускается c.bat вместо e.bat или наоборот.

И под конец рассмотрим ещё один вопрос. Как быть, если нужно контролировать порядок запуска не только bat-, но и exe-, и com-файлов?

Для запуска каждого exe- или com-файла можно создать свой bat-файл, тем самым задача будет сведена к уже рассмотренной. Между прочим, если вы используете для запуска файлов файловый менеджер, в котором не показываются файлы с атрибутом hidden (скрытый), то имеет смысл для этих exe- и com-файлов установить данный атрибут, чтобы не запустить их случайно.

Другие мои статьи о bat-файлах:

Страница Ивана Рощина > Статьи >