批处理脚本中嵌套标签的奇怪行为

Weird behavior for nested labels in batch script

这是批处理程序:

@echo off
SETLOCAL EnableDelayedExpansion
set /a incr=0

set arg1=%1
del test_output.csv > NUL 2>&1
del test_output.log > NUL 2>&1

set startTime=%time%
for /d %%i in ("%cd%\*") do call :run_test "%%i"
.\log_parser.exe
type test_output.csv
echo Start Time: %startTime%
echo Finish Time: %time%
exit /B

:run_test
  if not "%~nx1" == "shared" (
    echo Test: %~nx1
    cd %1

    del pass_fail_output.csv > NUL 2>&1
    echo Running...
    cd temp_root_fs
    start application.exe
    set /a incr=0
    :while1
      tasklist /fi "IMAGENAME eq application.exe" 2>NUL | find /i /n "application.exe">NUL
      if "%ERRORLEVEL%"=="0" (
        if %incr% leq 60 (
          echo Still running...
          timeout /t 1 > NUL 2>&1
          set /a incr+= 1
          goto :while1
        )
        echo Test timed out...
        taskkill /im application.exe /f
      )
      echo Test completed...
    cd logs
    .\pass_fail_parser.exe
    type log.log >> ..\..\..\test_output.log
    copy pass_fail_output.csv ..\..\
    cd ..\..\
  )

  echo Cleaning...
  rmdir /S /Q temp_root_fs
  cd ..
)

这是我的预期执行:

第一个循环工作正常,但这是我执行它时当前输出的样子:

Test: test1
Initializing...
Running...
Still running...
Still running...
Still running...
Still running...
Still running...
Still running...
Still running...
Still running...
Still running...
Still running...
Test completed...
        1 file(s) copied.
Cleaning...

我知道这不能正常工作,因为我还有 3 个文件夹用于测试,所以它应该继续到其他文件夹,但不知何故它似乎提前脱离了 for 循环。

我读过 /I option 据说可以防止 goto 跳出 iff 和 do 循环,但我不完全确定它是如何工作的(我尝试将它添加为参数,但它要么出错,要么似乎什么也没做)。

如有任何帮助,我们将不胜感激!

:run_test
  if not "%~nx1" == "shared" (
    echo Test: %~nx1
    cd %1

    del pass_fail_output.csv > NUL 2>&1
    echo Running...
    cd temp_root_fs
    start application.exe
    set /a incr=0

    CALL :while1

    echo Test completed...
    cd logs
    .\pass_fail_parser.exe
    type log.log >> ..\..\..\test_output.log
    copy pass_fail_output.csv ..\..\
    cd ..\..\
  )

  echo Cleaning...
  rmdir /S /Q temp_root_fs
  cd ..
)

GOTO :EOF

:while1
  tasklist /fi "IMAGENAME eq application.exe" 2>NUL | find /i /n "application.exe">NUL
  if "%ERRORLEVEL%"=="0" (
    if %incr% leq 60 (
      echo Still running...
      timeout /t 1 > NUL 2>&1
      set /a incr+= 1
      goto :while1
    )
    echo Test timed out...
    taskkill /im application.exe /f
  )

GOTO :EOF

在你的代码中,if not "%~nx1" == "shared" (到最后的)是一个code block。代码块中不允许使用标签。当 if 语句为 parsed 时,值 %var% 被当时那些变量的值替换,而不是由于块内执行的操作而导致的更改。当心

以上代码将:while1循环转换为由CALL :while1调用的内部子程序(冒号是必需的表示调用是内部子程序标签)

注意 GOTO :EOF 语句。这些将执行转移到物理文件末尾(冒号又是 required)首先是防止执行从 :run_test 进入 :while1流通。第二个是在 :while1 例程完成时强制 return 到 CALL :while1 之后的语句。 :while1 例程可以放在批处理主线中的 any goto 语句之后(即 not a goto 在一个代码块内)。