2

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

Вызов функции цикла использует 2 переменные.

  1. имя подфункции для вызова
  2. текст для вывода на экран для удобства пользователя

Вот как выглядят эти вызывающие линии

call :loop BackupDatabase "Taking database backup"
call :loop StopBGService "Stopping the background service"

Это сама функция цикла

:loop
    :retry
    echo %~2
    call :%~1

    IF %ERRORLEVEL% NEQ 0 (
        SET ERRORLEV=%ERRORLEVEL%
        ECHO Executing %~2 failed
        ECHO Error Level: %ERRORLEV%
        ECHO.

        set /p ans=Do you want to retry %~2 [y/n]^>
        if "%ans%"== "y" goto :retry
        if "%ans%"== "Y" goto :retry
    )
GOTO :EOF

Ниже вы найдете функции, которые вызываются каждым циклом

:BackupDatabase
    Perform database backup commands
GOTO :EOF

:StopBGService
    Perform stop background service commands
GOTO :EOF

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

1 ответ1

2

Проблема заключается в том, что в командной строке Windows / интерпретаторе командной строки (CLI), известном как CMD.EXE, есть ошибка (ну, я уверен, что Microsoft считает, что это особенность), когда она читает блок-конструкцию, такую как IF … ( … ) Или цикл FOR , он интерпретирует все %variable_name% variable_name % непосредственно перед выполнением цикла.  В вашем примере, если ans является нулевым, когда вы входите в блок IF %ERRORLEVEL% NEQ 0 ( … ) , тогда все вхождения %ans% внутри этого блока оцениваются как нулевые, даже если вы изменяете ans внутри блока.  Это можно увидеть, если оставить ECHO (или снова включить его непосредственно перед IF %ERRORLEVEL% NEQ 0 ).

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

setlocal enabledelayedexpansion

где-то рядом с началом вашего пакетного файла, и изменив код пользовательского диалога, чтобы он выглядел как

    set /p ans=Do you want to retry %~2 [y/n]^>
    if "!ans!" == "y" goto :retry
    if "!ans!" == "Y" goto :retry

используя !variable_name! Форма для активации отложенного расширения.  Смотрите SET /? и SETLOCAL /? для дополнительной информации.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .