0

我想做类似的事情:

start program1 ^>output
start program2 ^>output

并对输出进行排序,以便对输出进行排序。我不在乎哪个输出是第一个(程序 1 或程序 2),但我希望它是该程序输出的完整转储。

理想情况下,我想并行运行多个程序,并将输出全部显示到屏幕上,但是一个文件就可以了。我不需要在它运行时看到它,只要它完成后就可以理解它。

编辑:

如果我按照建议将它们输出到一个文件,然后在完成后合并它们,我会遇到等待所有程序完成的麻烦——所以,我需要一个 waitUntilAllTheStartsAreFinished 命令。

start program1 ^>output1
start program2 ^>output2
#... as many as I need
waitUntilAllTheStartsAreFinished 
TYPE output1
TYPE output2
delete output1
delete output2
4

2 回答 2

2

您可以使用循环和tasklist

:wait
rem just wait a second before looking again
ping -n 2 ::1 >nul 2>nul
tasklist 2>&1 | findstr /b "program1.exe program2.exe ..." >nul 2>&1 && goto wait

它只会继续下去,直到所有的program1.exe program2.exe ...都被终止。

于 2012-07-26T05:51:59.647 回答
1

Joey 建议的方法可行,但如果您的程序可以多次启动,则可能会出现问题。很难判断哪些任务是您想要监控的一次。

每个程序将在临时输出文件上拥有一个排他锁,直到程序完成。另一个进程重定向到同一文件的任何尝试都将失败。这可用于检测程序何时结束。

我使用 TIMEOUT 在轮询中插入延迟。如果您在 XP 之类没有 TIMEOUT 的系统上,则可以ping -n 2 ::1 >nul 2>nul改用。

我在代码中包含了有关此解决方案如何工作的大量文档。编辑-我通过删除一个不必要的代码块级别稍微简化了代码,并改进了文档。

@echo off
setlocal

REM Define a base name for the temporary output files. I've incorporated
REM a random number in the file name to generally make it safe to run this
REM master script multiple times simultaneously. It is unlikely a collision
REM will occur, but incorporating a timestamp in the name would make it more
REM reliable.
set "baseName=%temp%\output%random%_"
set /a "progCount=2, completedCount=0"

REM Start each program with both stdout and stderr redirected to a temporary
REM ouptut file. The program will have an exclusive lock on the output file
REM until it finishes executing. I've assumed the program is another batch file
REM and I use the START /B switch so that the programs are run in the same
REM window as this master script. Any console program will work, and the
REM /B switch is optional.
start /b "" ^"cmd /c test.bat ^>"%baseName%1" 2^>^&1^"
start /b "" ^"cmd /c test2.bat ^>"%baseName%2" 2^>^&1^"
REM etc.

REM Clear any existing completed flags, just in case
for /l %%N in (1 1 %progCount%) do set "completed%%N="

:loopUntilDone

REM Introduce a delay so we don't inundate the CPU while we poll
timeout /nobreak 1 >nul

REM Loop through each of the output file numbers.
REM Redirect the stderr for the DO block to nul so that if the inner
REM block redirection fails, the error message will be suppressed.
for /l %%N in (1 1 %progCount%) do (

  REM Only test this particular program if the output file has been
  REM created (in other words, the program has started) and we haven't
  REM already detected that it has finished. Also redirect an unused
  REM file handle to the output file in append mode.  The redirection will
  REM fail if the program has not completed. If the redirection fails then
  REM the IF block is not executed.
  if not defined completed%%N if exist "%baseName%%%N" (

      REM We are within the block, meaning the redirection succeeded and
      REM the program must have finished. So print out the results.
      echo(
      echo Ouput for program%%N
      echo ---------------------------------------------
      type "%baseName%%%N"

      REM Set a flag so we know this program has finished
      set completed%%N=1

      REM Increment the completed count so we know when we are done
      set /a completedCount+=1

  ) 9>>"%baseName%%%N"

) 2>nul

if %completedCount% neq %progCount% goto :loopUntilDone

del "%baseName%*"
于 2012-07-26T18:10:45.637 回答