Проблемы в реальном DOS со смешанными командами "goto" и "call" в пакетном меню - PullRequest
2 голосов
/ 12 октября 2019

Я создаю пакетное меню в MS-DOS 6.22, и мне нужно использовать if errorlevel со смешанными командами goto и call. У меня есть некоторые проблемы с заказом, потому что они не выполняются должным образом.
Я не могу запустить другие командные файлы без использования call, за исключением file6.bat, потому что мне нужно сохранить переменные среды.

Это пример меню:

:MENU
@echo off
echo [1] Choice 1
echo [2] Choice 2
echo [3] Choice 3
echo [4] Choice 4
echo [5] Choice 5
echo [6] Choice 6
echo [7] Choice 7
echo [8] Choice 8
echo [Y] Choice Y
echo [Z] Choice Z
choice /c12345678YZ /n /m "Select an option"

if errorlevel 10 call file7.bat
if errorlevel 9 file6.bat
if errorlevel 8 call file5.bat
if errorlevel 7 call file4.bat
if errorlevel 6 call file3.bat
if errorlevel 5 call file2.bat
if errorlevel 4 goto menu3
if errorlevel 3 goto menu2
if errorlevel 2 goto menu1
if errorlevel 1 call file1.bat

Это поведение:

  • Если я выберу 1, будет выполнено 4-е [goto menu3].
  • Если я выберу 2, 3, 4, 5, Y и Z, он ответит правильно.
  • Если я выберу 6, 7 и 8, ничего не произойдет.

Не могли бы вы помочь мне понять, как решить эту проблему?

1 Ответ

3 голосов
/ 13 октября 2019

Здесь важны три факта:

  1. COMMAND.COM в MS-DOS 6.22 обрабатывает одну строку за другой сверху донизу командного файла, кроме команды GOTO используется для продолжения обработки пакетного файла не на следующей строке, а на строке ниже строки с меткой, указанной в качестве параметра для команды GOTO .

  2. Командный процессор DOS продолжает обработку пакетного файла в другом пакетном файле без возврата обратно в текущий пакетный файл, если другой командный файл указан в командной строке без использования команды CALL .

  3. Условие if errorlevel X означает ЕСЛИ ОШИБКА УРОВНЯ БОЛЬШЕ ИЛИ РАВЕНА 1 . Необходимо использовать два условия, чтобы проверить, равен ли код выхода команды или приложения определенному номеру. Необходимый синтаксис: if errorlevel X if not errorlevel X+1 command. Это похоже на ЕСЛИ ОШИБКА УРОВНЯ РАВНА X из-за ОШИБКА должна быть БОЛЬШЕ ИЛИ РАВНО X И МЕНЬШЕ, ЧЕМ X + 1 . Эти два условия верны только ЕСЛИ ОШИБКА УРОВНЯ РАВНА X . Пример: if errorlevel 6 if not errorlevel 7 call file3.bat приводит к вызову только file3.bat ЕСЛИ ОШИБКА УРОВНЯ РАВНА 6 .

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

Вариант использования 1: Пользователь нажимает клавишу Z .

  1. CHOICE.COM выходит со значением 10в ERRORLEVEL.
  2. Первое условие if errorlevel 10 - это true , и поэтому командный файл file7.bat * называется , который вызывается процессором команд.
  3. COMMAND.COM продолжается после следующей IF строки условия после завершения обработки file7.bat, за исключением того, что она содержит команду EXIT , которая приводит к выходу из командного процесса независимо от иерархии вызовов, если он действительноВыполнено.
  4. Второе условие if errorlevel 9 оценивает не код завершения CHOICE.COM, но код завершения, возвращаемый пакетным файлом file7.bat в основной пакетный файл. Код выхода, возвращаемый file7.bat, скорее всего, 0, и поэтому это второе условие и все остальные ниже оцениваются как false .

Вариант использования 2: Пользователь нажимает клавишу Y .

  1. CHOICE.COM выходит со значением 9, присвоенным ERRORLEVEL.
  2. Первое условие if errorlevel 10 is false .
  3. Второе условие if errorlevel 9 равно true , что приводит к выполнению file6.bat. Команда CALL здесь не используется. По этой причине COMMAND.COM не возвращается к основному пакетному файлу после завершения обработки file6.bat. По этой причине все, что ниже if errorlevel 9 file6.bat, не имеет значения при этом условии: true , поскольку обработка пакетного файла заканчивается обработкой file6.bat.

Вариант использования3: Пользователь нажимает клавишу 8 .

  1. CHOICE.COM выходит со значением 8, присвоенным ERRORLEVEL.
  2. Первое условиеif errorlevel 10 is false .
  3. Второе условие if errorlevel 9 is false .
  4. Третье условие if errorlevel 8 is true и, следовательно, пакетный файл file5.bat вызывается командным процессором.
  5. COMMAND.COM продолжается в следующей строке условия IF после завершения обработки file5.batза исключением того, что она содержит команду EXIT , которая также выполняется.
  6. Четвертое условие if errorlevel 7 вычисляет код завершения, возвращаемый пакетным файлом file5.bat в основной пакетный файл, который является наиболеевероятно 0 и, следовательно, это четвертое условие и все остальные ниже оцениваются как ложно .

Поведение более или менее одинаково при нажатии пользователем клавиши 7 , 6 или 5 .

Вариант использования 4: Пользователь нажимает клавишу 4 .

  1. CHOICE.COM выходит со значением 4, присвоенным ERRORLEVEL.
  2. Первые шесть условий оценивают все как false .
  3. Седьмое условие if errorlevel 4 - true , и поэтому команда GOTO выполняется, что приводит к продолжению обработки пакетного файла в строке ниже строки с меткой menu3. Таким образом, другие условия IF не имеют значения в этом случае использования.

Поведение более или менее одинаково при нажатии пользователем клавиши 3 или 2 .

Вариант использования 5: Пользователь нажимает клавишу 1 .

  1. CHOICE.COM выходит со значением 1 присвоено ERRORLEVEL.
  2. Первые девять условий оценивают все как false .
  3. Последнее условие if errorlevel 9 равно true ипоэтому пакетный файл file1.bat называется командным процессором.
  4. COMMAND.COM продолжается в строке после завершения обработки file1.bat, за исключением выполнения команды EXIT во время обработки file1.bat.

Существует как минимум три потенциальных проблемы с этим кодом:

  1. Последний код завершения выполненной команды или приложения с именем командный файл определяет поведение обработки в главном командном файле. Это на самом деле не нужно.
  2. Если ни одна из команд в вызываемом пакетном файле не изменяет значение ERRORLEVEL, как вызываемый пакетный файл, содержащий только серию set variable=value, следующая IF условие ниже условия IF , приводящее к вызову другого пакетного файла, также true , что приводит к вызову еще одного пакетного файла или продолжению обработки пакетного файла по кодудля menu3.
  3. Код под последним условием if errorlevel 1 определяет, что будет дальше с любым другим пакетным файлом , называемым , внутри этого основного пакетного файла в случае выхода всех этих пакетных файловсо значением 0.

Третья проблема может быть легко решена путем записи следующего в основной пакетный файл после последнего условия if errorlevel 1 либо goto MENU, чтобы продолжить обработку пакетного файла наверху с повторной печатьюменю или goto ENDBAT с последней строкой в ​​главном пакетном файле, равной :ENDBAT, чтобы продолжить обработку пакетного файла в конце пакетного файла, что означает завершение процедурыИспользование этого пакетного файла.

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

@echo off
:MainMenu
cls
echo [1] Choice 1
echo [2] Choice 2
echo [3] Choice 3
echo [4] Choice 4
echo [5] Choice 5
echo [6] Choice 6
echo [7] Choice 7
echo [8] Choice 8
echo [Y] Choice Y
echo [Z] Choice Z
choice /C:12345678YZ /N /M "Select an option:"

if errorlevel 10 set BatFile=7
if errorlevel 9 if not errorlevel 10 file6.bat
if errorlevel 8 if not errorlevel 9 set BatFile=5
if errorlevel 7 if not errorlevel 8 set BatFile=4
if errorlevel 6 if not errorlevel 7 set BatFile=3
if errorlevel 5 if not errorlevel 6 set BatFile=2
if errorlevel 4 if not errorlevel 5 goto Menu3
if errorlevel 3 if not errorlevel 4 goto Menu2
if errorlevel 2 if not errorlevel 3 goto Menu1
if errorlevel 1 if not errorlevel 2 set BatFile=1

call file%BatFile%.bat
set BatFile=
goto MainMenu

:Menu3
echo Here would be shown menu 3.
goto ENDBAT

:Menu2
echo Here would be shown menu 2.
goto ENDBAT

:Menu1
echo Here would be shown menu 1.
goto ENDBAT

:ENDBAT

Цель каждого вызываемого командного файла - продолжить отображение главного меню после завершения обработки вызванного пакетного файла. По этой причине достаточно определить переменную среды, такую ​​как BatFile, с номером вызываемого пакетного файла и убедиться, что всегда только одно IF условие true в соответствии с errorlevel устанавливается CHOICE.COM.

Приведенный выше код приводит к выполнению file6.bat при нажатии пользователем клавиши Y с игнорированием оставшихся строк в этом главном пакетном файле. Обработка пакетного файла продолжается нажатием клавиши 2 , 3 или 4 на соответствующем коде для подменю 1, 2 или 3. Но для клавиш 1 , 5 до 8 и 7 называется соответствующим пакетным файлом, затем определенная переменная среды BatFile не определенаи обработка пакетного файла продолжается, снова печатая главное меню и предоставляя пользователю возможность сделать еще один выбор.

Конечно, можно также назначить полное имя файла пакетного файла для вызова переменной среды BatFile. только его номер, если вызываемые пакетные файлы имеют разные имена и просто расширение файла одинаково для всех вызываемых пакетных файлов. В этом случае командная строка с CALL будет call %BatFile%.bat.

...