Batch file 为/L循环嵌套并退出循环的批处理文件

Batch file 为/L循环嵌套并退出循环的批处理文件,batch-file,for-loop,nested,Batch File,For Loop,Nested,这段代码没有像我期望的那样通过for循环。我试着做这样的事,但没用。有什么建议吗 编辑 当可执行文件完成运行时,ERRORLEVEL不是1 SETLOCAL ENABLEDELAYEDEXPANSION set list=A B C D E FOR %%a IN (%list%) DO ( start %%a.exe > ouput_%%a.txt echo 120, 30 second loops = 60 min FOR /L %%i IN (1,1,120)

这段代码没有像我期望的那样通过for循环。我试着做这样的事,但没用。有什么建议吗

编辑

当可执行文件完成运行时,ERRORLEVEL不是1

SETLOCAL ENABLEDELAYEDEXPANSION
set list=A B C D E

FOR %%a IN (%list%) DO (
    start %%a.exe > ouput_%%a.txt
    echo 120, 30 second loops = 60 min
    FOR /L %%i IN (1,1,120) DO (
        REM pause for 30 seconds
        ping 1.1.1.1 -n 1 -w 30000 > nul

        echo find the running executable
        tasklist | findstr %%a.exe > nul
        REM !ERRORLEVEL!
        REM exit the script if no executable is found (i.e it has run successfully)
        if !ERRORLEVEL! equ 1 goto success
   )
   REM kill executable if we haven't exited yet
   taskkill /f /im %%a.exe
   :success
)

for
循环中执行
goto
命令会中断循环迭代。这适用于所有嵌套的
for
循环

但是,您可以做的是将内部
for
循环移动到一个子例程中(使用
call
调用它)。此循环可通过
goto
命令终止,但从子程序返回后,循环的剩余(外部)
不受影响,并继续迭代

SETLOCAL ENABLEDELAYEDEXPANSION
set list=A B C D E

FOR %%a IN (%LIST%) DO (
    start %%a.exe > ouput_%%a.txt
    REM 120, 30 second loops = 60 min
    call :innerloop %%a
    REM kill executable if we haven't exited yet
    taskkill /f /im %%a.exe
)
goto :eof
:innerloop
FOR /L %%i IN (1,1,120) DO (
    REM pause for 30 seconds
    ping 1.1.1.1 -n 1 -w 30000 > nul

    REM find the running executable
    tasklist | findstr %%a.exe > nul
    REM !ERRORLEVEL!
    REM exit the script if no executable is found (i.e it has run successfully)
    if %ERRORLEVEL% equ 1 goto :next
)
:next
goto :eof
在此,我将内部
for
循环移动到一个子例程
:SUBLOOP
,该子例程由
调用:SUBLOOP%%a.exe
从外部
for
循环调用,将当前值传递给它进行处理(可执行文件
%%a.exe
)<代码>错误级别
在终止时传输到调用例程。
:SUBLOOP
返回外部
for
循环后,检查
ERRORLEVEL
是否为零,如果为零,则终止当前迭代的可执行文件的进程。
&&
是一个条件命令分隔符,只有在第一个命令成功时,即清除了
ERRORLEVEL
时,才执行第二个命令。
注意外部
for
循环后的
exit/B
命令,这是在外部循环完成后不无意执行
子循环
部分所必需的

注意:
goto
不会立即终止
for
循环迭代;事实上,每个挂起的迭代仍然以静默方式计数,但是不再执行
for
主体的命令。因此,具有大量迭代的循环可能需要相当长的时间才能继续批处理执行。谢谢@foxidrive

此外,如果
goto
目标标签被放置在
for
主体中,则循环完全完成后,执行将在该点继续。然后,该点之后的任何代码都将被视为“正常”代码,而不是
正文的
部分。

在编辑的代码中,您需要使用
!错误等级而不是
%ERRORLEVEL%
!此外,您根本不是在查询
!错误等级!在“循环”的外部
。您可以测试
call:innerloop%%a | | taskkill/f/im%%a.exe
是否有效(这意味着
taskkill
仅在
call
返回非零
ERRORLEVEL
时才会执行)。如果一个可执行文件仍在运行,则此代码会导致可执行文件彼此重叠。抱歉,最后一件事。添加
/WAIT
开关时,
输出%%a.txt
中没有任何文本。如何解决此问题?为什么我需要
/WAIT
?存在内部for循环是为了在一个小时过去或可执行文件完成执行之前不允许外部循环运行@aschipfl@aschipfl
goto
命令不会立即终止for循环-它会静默地计算每一个尚未通过的过程。尝试一个
for循环
计数高达1000万次,并在达到5000次时使用goto来查看发生了什么。@aschipfl是的,它停止处理命令-但您编写的
循环会立即终止迭代
,它不会,因为长循环可能会在继续批处理脚本之前再运行15分钟等等。您的描述应该改写为循环可能需要相当长的时间才能继续批处理。有一些技术可以立即退出
for循环
,但这不是其中之一。
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
set list=A B C D E

FOR %%a IN (%list%) DO (
    start %%a.exe > ouput_%%a.txt
    echo 120, 30 second loops = 60 min
    REM kill executable if we haven't exited yet
    call :SUBLOOP %%a.exe && taskkill /f /im %%a.exe
)
exit /B

:SUBLOOP
FOR /L %%i IN (1,1,120) DO (
    REM pause for 30 seconds
    timeout /T 30 /NOBREAK > nul
    echo find the running executable
    tasklist | findstr /I /B "%~1" > nul
    REM !ERRORLEVEL! is 0 if found and 1 otherwise
    REM exit the script if no executable is found
    REM (i.e it has run successfully)
    if !ERRORLEVEL! equ 1 goto :EOF
)
exit /B 0