首页 > 解决方案 > 批处理脚本中嵌套标签的奇怪行为

问题描述

这是批处理程序:

@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 循环。

我已经阅读了据说可以防止 goto 脱离 iff 并执行循环的/I 选项,但我不完全确定它是如何工作的(我尝试将它添加为参数,但它要么出错,要么似乎没有做任何事情) .

任何帮助将不胜感激!

标签: batch-filecommand-line

解决方案


: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. 代码块中不允许使用标签。%var%if语句被当时那些变量的值替换时,这些值被替换parsed,而不是由于在块内执行的操作而导致的更改。谨防延迟扩张陷阱

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

注意GOTO :EOF语句。这些将执行转移到文件的物理结尾(冒号再次是必需的)首先是为了防止执行从:run_test进入:while1通过流过。第二种是在例程完成CALL :while1时强制返回到后面的语句。:while1:while1例程可以放在批处理主线中的任何 goto语句之后(即不在goto代码块内)。


推荐阅读