【问题标题】:Can't run multiple batch files sequentially from master batch file in Win7无法从 Win7 中的主批处理文件顺序运行多个批处理文件
【发布时间】:2013-07-27 23:48:44
【问题描述】:

我有一堆批处理文件,每个批处理文件启动一堆可执行文件以同时运行。每个批处理文件启动 30 个可执行文件。当这 30 个完成后,我希望运行下一批可执行文件,一次再运行 30 个。 .exe 是使用批处理文件中的“开始”命令调用的,它们工作得很好 - 我可以为每组 30 个 exe 运行单独的批处理文件,它们可以像应该的那样同时运行。

我创建了一个“主”批处理文件,它调用每个子批处理文件,但我不知道如何让它按顺序运行子批处理文件,等待一个完成后再开始下一个。

如果主批处理文件是这样的:

Batch1.bat
Batch2.bat
Batch3.bat

那么只有第一个批处理文件被调用 - 其他的永远不会被调用。

如果主批处理文件是这样的:

call Batch1.bat
call Batch2.bat
call Batch3.bat

然后所有子批处理文件同时开始运行,我得到数百个可执行文件试图同时启动。

如何让主批处理文件调用第一个批处理文件,等待它完成,然后调用下一个,等待它完成,然后调用下一个,等等?

提前致谢,

游戏

【问题讨论】:

  • 问题不在于catch文件是并行运行的。那是您正在使用“开始”来运行exes。 “开始”不等待程序退出。删除“开始”关键字。
  • 我想同时运行每个批处理文件中的所有30个exe,所以我需要使用“开始”。如果我不使用“开始”,则 30 个 exe 不会同时运行。我希望批处理文件连续运行,但我希望每个批处理文件中的 exe 同时运行。
  • start "Myexe one" one.exestart "Myexe two" two.exe等开始你的前任怎么样?然后您可以使用tasklist |find "Myexe" 检查其中一些是否仍在运行
  • 那么你得到的正是你想要的。第一个批处理文件无需等待即可同时启动 30 个程序。然后第二个批处理文件不等待同时启动另外30个程序,总共60个。然后第三个批处理文件再启动30个,总共90个。
  • 是的 - 这就是 tasklist 的用途:检查是否所有的 exe 都已完成。 (当然,您必须将其嵌入到循环中:all of them gone? yes -> exit, else wait again

标签: batch-file


【解决方案1】:

当启动另一个批处理时,CALL 将在同一个窗口中启动它,并且被调用的批处理可以访问相同的变量上下文。所以它也可以改变影响调用者的变量。

在您的批处理文件中使用等待来调用可执行文件将等待它们退出之前。

START /WAIT  batch1.bat
START /WAIT batch2.bat

希望对你有帮助

【讨论】:

  • 谢谢,但这似乎不起作用。在 Batch1.bat 之后它仍然停止。然而,还有两个 cmd.exe 窗口就坐在那里打开。一个具有带有“START /WAIT Batch1.bat”的命令行,另一个似乎显示了 Batch1.bat 中的所有命令。我是否需要从子批处理文件中添加某种“返回”语句?退出命令不起作用。
  • 它的工作原理是等待 batch1.bat 退出,然后按照您的要求运行 batch2.bat。你的 batch1.bat 没有退出的原因是你必须找到的。您也可以使用start "" /w /b batch1.bat,它将等待并在同一个 cmd 窗口中运行它。 "" 用于防止命令中的引用路径引起问题。
  • 如果我在主批处理文件中使用 'start "" /w /b batch1.bat' 等,那么它会一次运行所有批处理文件,并且所有批处理中的所有可执行文件都在同时。确实-看起来batch1.bat永远不会退出-该批处理文件的窗口只是坐在那里,带有命令提示符,等待发生某些事情。我如何告诉 batch1.bat 关闭它的窗口?我想这就是为什么第二个窗口坐在那里的原因——它是等待 batch1.bat 窗口关闭的主批处理文件的窗口。我的问题没有解决,但我正在学习一些东西......!还有其他想法吗?
  • 包括可以找到批处理文件的目录。例如:call "C:\Batch1.bat",打电话给"C:\Batch2.bat"等等。
【解决方案2】:

对不起。我认为这里有一个误解。如果您的主批处理文件是这样的:

call Batch1.bat
call Batch2.bat
call Batch3.bat

然后在 Batch1.bat 结束后调用 Batch2.bat,以此类推。您可以做一个小测试来确认这一点。另一方面,每个 BatchN.bat 程序是否可能使用相同的变量?如果是这样,那么从 Batch1.bat 中留下的最后一个值可能会干扰 Batch2.bat,依此类推。在这种情况下,您必须在每个批处理文件的开头添加一个Setlocal 命令。

【讨论】:

  • 每个子批处理文件(batch1.bat、batch2.dat 等)都将“set tempDir=%CD%”作为第一行。这样做是因为它从当前根目录更改目录,在该目录中启动 .exe,然后更改回根目录,以便它可以更改到下一个目录并启动下一个 .exe。我在有和没有 setlocal 的情况下都试过了,没有区别。我不希望它 - 设置的变量应该总是相同的。
【解决方案3】:

我必须为多个文件运行数据导出程序。我的解决方案:

MasterBatch.bat:

@echo off
start /w batch1.bat
start /w batch2.bat

Batch1.bat

@echo off
cmd /c "c: & cd Program Files (x86)/PATH & targetProgram.exe -parametersToExportVideo1"
EXIT

Batch2.bat

@echo off
cmd /c "c: & cd Program Files (x86)/PATH & targetProgram.exe -parametersToExportVideo2"
EXIT

它可能适用于运行程序的其他问题。

【讨论】:

    【解决方案4】:

    您必须创建一个信号机制来感知 EXE 完成。

    我会创建一个第三级批处理来运行每个 EXE,在执行 EXE 之前创建一个临时文件并在之后删除它。

    在子批次中,我会等到没有更多的临时文件。

    所以,初始批次:

    call Batch1.bat
    call Batch2.bat
    call Batch3.bat
    

    子批次:

    Set Index=0
    Call :Exec exefile1 args ...
    Call :Exec exefile2 args ...
    ...
    :WaitAll
    If Exist %Temp%\RUNNING_EXE.*.TMP GoTo :WaitAll
    GoTo :EOF
    
    :Exec
    Set /A Index+=1
    Echo %Index% > %Temp%\RUNNING_EXE.%Index%.TMP
    Start Batch_3rd.BAT %*
    GoTo :EOF
    

    最后是第 3 级批次,Batch_3rd.BAT:

    %*
    Del %Temp%\RUNNING_EXE.%Index%.TMP
    

    %* 是从子批处理(exe+参数)传递的参数,%Index% 是正确的,因为start 在创建时从子批处理复制环境,子批处理不会更改此副本。 最后一点:您可能可以将所有批处理合并到一个批处理文件中,递归调用它。

    【讨论】:

      【解决方案5】:

      我的解决方案:

      1) 我有四个批处理文件: Parent.bat 和 Batch1.bat、Batch2.bat、Batch3.bat

      2) Parent.bat 包含以下几行(请注意):

      调用 Batch1.bat > result1.log

      调用 Batch2.bat > result2.log

      调用 Batch3.bat > result3.log

      3) 确保“进入每个子批处理文件的末尾”,您有一个回显语句。 在这个 echo 语句之后不应该有任何代码......

      说Batch1.bat文件的内容是:

      回声开始

      robocopy "C:\Users\DD\Documents\A" "C:\Users\DD\Documents\B"

      回声结束

      回显 this_is_the_last_line

      【讨论】:

        【解决方案6】:

        只是为了测试,我会使用简单的子批次,比如(它们都是一样的)

        @echo off
            for /l %%a in (1 1 5) do start "" notepad.exe
        

        还有一个主批处理文件

        @echo off
            setlocal enableextensions disabledelayedexpansion
        
            set "flagFile=%temp%\%random%%random%%random%.tmp"
        
            for %%a in ( "batch1.cmd" "batch2.cmd" "batch3.cmd" ) do (
                call :startBatch %%a "%flagFile%"
            )
        
        :retryClean
            echo %time% waiting for last batch to end
            2>nul ( 9>"%flagFile%" break ) || ( >nul timeout 5 & goto :retryClean )
            del /q "%flagFile%"
        
            echo DONE
            pause
            goto :eof
        
        :startBatch batchFile flagFile
            echo %time% waiting to start "%~1"
            2>nul ( 9>"%~2" call "%~1" ) || ( >nul timeout 5 & goto :startBatch )
            echo %time% [ "%~1" ] STARTED
            goto :eof
        

        此代码以主动重定向(使用用户可用流 9)到临时标志文件开始每个子批次。这将锁定标志文件,直到从子批次启动的所有进程都结束,因为在进程创建期间继承了重定向。

        我们所要做的就是继续尝试使用相同的重定向启动下一个批处理文件:

        • 如果文件仍处于锁定状态(进程正在运行),则无法启动批处理文件,请等待 5 秒后重试

        • 如果文件未锁定,则可以创建重定向并启动下一个批处理文件。

        【讨论】:

          猜你喜欢
          • 2012-12-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-01
          相关资源
          最近更新 更多