如何从Windows shell生成多个进程并等待它们全部完成?

如何从Windows shell生成多个进程并等待它们全部完成?,windows,scripting,batch-file,Windows,Scripting,Batch File,我想从Windows批处理脚本执行以下操作: start proc1.exe start proc2.exe ... start procN.exe <wait for all N processes to complete> <-- What do I put here? start proc1.exe 启动proc2.exe ... 启动procN.exe 如果您编写.NET代码或Win32 C/C++代码来启动进程,则可以执行此操作,但无法在批处理文件中执行此操

我想从Windows批处理脚本执行以下操作:

start proc1.exe

start proc2.exe

...

start procN.exe

<wait for all N processes to complete> <-- What do I put here?
start proc1.exe
启动proc2.exe
...
启动procN.exe

如果您编写.NET代码或Win32 C/C++代码来启动进程,则可以执行此操作,但无法在批处理文件中执行此操作。一旦使用
start
使proc1.exe异步运行,就没有批处理命令允许您稍后返回并等待它完成

但是,您可以使用为批处理、Python等设计的脚本语言之一轻松地完成这项工作

举个例子,这里是。自以来,所有版本的Windows都包含WSH。所以这个脚本应该在任何地方运行

此脚本启动两个程序并等待它们都完成。另存为
start2.wsf
。然后在批处理文件中使用它:

start2.wsf "prog1.exe" "prog2.exe"


<package>
  <job id="Start 2 Procs">
    <runtime>
      <description>Start 2 programs and wait for them both to finish.
      </description>
      <unnamed
        name="program"
        helpstring="the program to run"
        many="false"
        required="2"
      />
      <example>
        Example: Start2.wsf "cl -c foo.obj" "cl -c bar.obj"
      </example>
    </runtime>

    <script language="JScript">

      if (WScript.Arguments.length < 2)
      {
        WScript.Arguments.ShowUsage();
        WScript.Quit();
      }

      var proc1 = WScript.Arguments.Unnamed.Item(0);
      var proc2 = WScript.Arguments.Unnamed.Item(1);

      var Shell = WScript.CreateObject("WScript.Shell");
      var oProc1 = Shell.Exec(proc1);
      var oProc2 = Shell.Exec(proc2);

      while (oProc1.Status == 0 && oProc2.Status == 0)
      {
        WScript.Sleep(1000);
      }
    </script>
  </job>
</package>
start2.wsf“prog1.exe”prog2.exe
启动两个程序并等待它们都完成。
示例:Start2.wsf“cl-cfoo.obj”“cl-cbar.obj”
if(WScript.Arguments.length<2)
{
WScript.Arguments.ShowUsage();
WScript.Quit();
}
var proc1=WScript.Arguments.Unnamed.Item(0);
var proc2=WScript.Arguments.Unnamed.Item(1);
var Shell=WScript.CreateObject(“WScript.Shell”);
var oProc1=Shell.Exec(proc1);
var oProc2=Shell.Exec(proc2);
而(oProc1.Status==0&&oProc2.Status==0)
{
WScript.Sleep(1000);
}

这很难看,但您可以将每个命令包装在另一个批处理文件中,该批处理文件运行该命令,然后发出命令完成的信号。主批处理文件将异步调用这些批处理文件中的每一个,并在循环中等待信号

例如:

main.bat

start cmd /c proc1.bat
start cmd /c proc2.bat
:wait
sleep 1
IF NOT EXIST proc1done GOTO wait
IF NOT EXIST proc2done GOTO wait
del proc1done
del proc2done
echo All processes are complete
proc1.exe
echo Done > proc1done
proc1.bat

start cmd /c proc1.bat
start cmd /c proc2.bat
:wait
sleep 1
IF NOT EXIST proc1done GOTO wait
IF NOT EXIST proc2done GOTO wait
del proc1done
del proc2done
echo All processes are complete
proc1.exe
echo Done > proc1done

sleep命令在中可用。如果你没有,你可以在本地主机上使用ping来减缓这种紧张的循环。

通常你会使用Python来做类似的事情,但这里是这样的(受本文和其他文章的启发):


我发现了一个很好的解决方案,使用了一个名为“Yori”的替代shell。您可以阅读更多关于它的信息,并从下载。Yori是开源的,其代码库位于

Yori使实现并行进程执行并等待它们完成变得很容易。本质上,您需要做的是将不同的子进程作为所谓的“作业”启动,然后使用内部命令“wait”等待它们完成。通过在命令末尾添加特殊字符“&!”可以将任何进程作为作业启动。大概是这样的:

ping localhost &!
ping someotherhost &!
wait
您可以将依赖于Yori的命令放在单独的批处理文件中(具有Yori批处理扩展名“.ys1”),并从Windows批处理中调用该文件,例如使用以下命令:

echo Let Yori do the parallel execution of some lengthy operations...
start /wait /b /belownormal yori.exe -c "your-yori-script.ys1"
echo All the lengthy operations are finished, continue with the next steps...

我可能更喜欢让主批处理文件创建文件,然后让proc文件删除它们。这样,如果在上一次运行中只完成了部分流程,您就不会冒看到流程已完成的风险。(在运行start命令之前,您可以通过删除任何现有文件来解决这个问题,但据我所知,如果您对其进行更改,代码应该会稍微少一些)。谢谢。我想现在就这样吧。我需要一个简单的Win32应用程序来长期生成。如果你想从批处理文件中生成一个进程而不使用新的命令窗口,请使用
start/B proc1.bat
你错了。你可以用球棒来做。(1)在不启动的情况下调用proc.exe或(2)使用
START/WAIT
命令行参数。请参阅
帮助启动
@PA:您的两个建议都不允许进程并行运行。@杰里米:您是对的,这不是我们的初衷。其目的是正确地声明您可以调用一个程序并等待它完成。我的评论是针对您编写的一些措辞,意思是.BAT不能等待进程完成。在对你的答案进行了主要编辑之后,我的评论就没有意义了。zr:我添加了一个脚本代码来实现这一点。
echo Let Yori do the parallel execution of some lengthy operations...
start /wait /b /belownormal yori.exe -c "your-yori-script.ys1"
echo All the lengthy operations are finished, continue with the next steps...