无法在批处理循环中获得正确的行为

无法在批处理循环中获得正确的行为

我在批处理文件中使用以下循环单独调用文件中的“函数”,首先显示文本,最后检查和显示错误级别。

调用循环函数使用 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

问题在于 Windows 命令提示符/命令行解释器 (CLI),即 CMD.EXE,有一个错误(好吧,我相信微软认为这是一个功能),当它读取一个块结构IF … ( … )或一个FOR循环时,它会解释所有变量%variable_name%立即地,在执行循环之前。在您的示例中,ans当您进入块时 if 为 null IF %ERRORLEVEL% NEQ 0 ( … ),那么%ans%该块内的所有出现的 都将求值为 null,即使您在块内进行更改也是如此。如果您保持开启(或在 之前将其重新开启),ans则可以看到这一点。ECHOIF %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 /?

相关内容