45

Windows バッチ ファイルで複数のプロセスを並行して実行できるツールはありますか? Linux 用の興味深いツール ( parallelおよびPPSS )をいくつか見つけましたが、Windows プラットフォーム用のツールが必要です。

おまけ: ツールが複数のマシン間でプロセスを簡単な方法で分散し、プロセスをPsExecとしてリモートで実行できるようになれば素晴らしいことです。

例: 次の for ループでそれを希望します

for %F in (*.*) do processFile.exe %F

マルチコア CPU を利用するために、限られた量の processFile.exe のインスタンスが並行して実行されます。

4

6 に答える 6

57

編集-オプションで各プロセスの出力を表示するようにスクリプトを変更しました

これは、コマンドのリストを確実に並行して実行し、一度にn 個を超えるプロセスを起動しないネイティブ バッチ ソリューションです。

PSEXEC を介して特定の CPU またはリモート マシンにプロセスを分散するメカニズムも組み込まれていますが、その機能はテストしていません。

これを機能させる秘訣は、標準出力または未定義のハンドルをロック ファイルにリダイレクトする CMD プロセスを介して各コマンドを開始することです。プロセスは、終了するまでファイルの排他ロックを維持します。プロセスがどのように終了するか (通常の終了、クラッシュ、プロセスの強制終了) は関係ありません。ロックは終了するとすぐに解放されます。

マスター スクリプトは、同じロック ファイルへのリダイレクトを試行することで、プロセスがまだアクティブであるかどうかをテストできます。プロセスがまだアクティブな場合、リダイレクトは失敗し、終了した場合は成功します。

デフォルトでは、スクリプトは各プロセスの出力を無視します。このオプションを第 1 パラメーターとして開始すると、/Oインターリーブせずに各プロセスの出力が表示されます。

私のデモでは、プロセス制限を 4 に設定し、さまざまな長さの一連の PING コマンドを単純に実行します。

XP、Vista、および Windows 7 でこれをテストしました。

@echo off
setlocal enableDelayedExpansion

:: Display the output of each process if the /O option is used
:: else ignore the output of each process
if /i "%~1" equ "/O" (
  set "lockHandle=1"
  set "showOutput=1"
) else (
  set "lockHandle=1^>nul 9"
  set "showOutput="
)

:: The list of commands could come from anywhere such as another file
:: or the output of another command. For this demo I will list the
:: commands within this script - Each command is prefixed with :::
::: ping /n 05 ::1
::: ping /n 20 ::1
::: ping /n 10 ::1
::: ping /n 15 ::1
::: ping /n 07 ::1
::: ping /n 05 ::1
::: ping /n 20 ::1
::: ping /n 10 ::1
::: ping /n 15 ::1
::: ping /n 07 ::1

:: Define the maximum number of parallel processes to run.
:: Each process number can optionally be assigned to a particular server
:: and/or cpu via psexec specs (untested).
set "maxProc=4"

:: Optional - Define CPU targets in terms of PSEXEC specs
::           (everything but the command)
::
:: If a CPU is not defined for a proc, then it will be run on the local machine.
:: I haven't tested this feature, but it seems like it should work.
::
:: set cpu1=psexec \\server1 ...
:: set cpu2=psexec \\server1 ...
:: set cpu3=psexec \\server2 ...
:: etc.

:: For this demo force all CPU specs to undefined (local machine)
for /l %%N in (1 1 %maxProc%) do set "cpu%%N="

:: Get a unique base lock name for this particular instantiation.
:: Incorporate a timestamp from WMIC if possible, but don't fail if
:: WMIC not available. Also incorporate a random number.
  set "lock="
  for /f "skip=1 delims=-+ " %%T in ('2^>nul wmic os get localdatetime') do (
    set "lock=%%T"
    goto :break
  )
  :break
  set "lock=%temp%\lock%lock%_%random%_"

:: Initialize the counters
  set /a "startCount=0, endCount=0"

:: Clear any existing end flags
  for /l %%N in (1 1 %maxProc%) do set "endProc%%N="

:: Launch the commands in a loop
:: Modify the IN () clause as needed to retrieve the list of commands
  set launch=1
  for /f "tokens=* delims=:" %%A in ('findstr /b ":::" "%~f0"') do (
    if !startCount! lss %maxProc% (
      set /a "startCount+=1, nextProc=startCount"
    ) else (
      call :wait
    )
    set cmd!nextProc!=%%A
    if defined showOutput echo -------------------------------------------------------------------------------
    echo !time! - proc!nextProc!: starting %%A
    2>nul del %lock%!nextProc!
    %= Redirect the lock handle to the lock file. The CMD process will     =%
    %= maintain an exclusive lock on the lock file until the process ends. =%
    start /b "" cmd /c %lockHandle%^>"%lock%!nextProc!" 2^>^&1 !cpu%%N! %%A
  )
  set "launch="

:wait
:: Wait for procs to finish in a loop
:: If still launching then return as soon as a proc ends
:: else wait for all procs to finish
  :: redirect stderr to null to suppress any error message if redirection
  :: within the loop fails.
  for /l %%N in (1 1 %startCount%) do 2>nul (
    %= Redirect an unused file handle to the lock file. If the process is    =%
    %= still running then redirection will fail and the IF body will not run =%
    if not defined endProc%%N if exist "%lock%%%N" 9>>"%lock%%%N" (
      %= Made it inside the IF body so the process must have finished =%
      if defined showOutput echo ===============================================================================
      echo !time! - proc%%N: finished !cmd%%N!
      if defined showOutput type "%lock%%%N"
      if defined launch (
        set nextProc=%%N
        exit /b
      )
      set /a "endCount+=1, endProc%%N=1"
    )
  )
  if %endCount% lss %startCount% (
    1>nul 2>nul ping /n 2 ::1
    goto :wait
  )

2>nul del %lock%*
if defined showOutput echo ===============================================================================
echo Thats all folks^^!

プロセス出力を無視するサンプル実行からの出力を次に示します。

12:24:07.52 - proc1: starting  ping /n 05 ::1
12:24:07.52 - proc2: starting  ping /n 20 ::1
12:24:07.53 - proc3: starting  ping /n 10 ::1
12:24:07.54 - proc4: starting  ping /n 15 ::1
12:24:11.60 - proc1: finished  ping /n 05 ::1
12:24:11.60 - proc1: starting  ping /n 07 ::1
12:24:16.66 - proc3: finished  ping /n 10 ::1
12:24:16.66 - proc3: starting  ping /n 05 ::1
12:24:17.68 - proc1: finished  ping /n 07 ::1
12:24:17.68 - proc1: starting  ping /n 20 ::1
12:24:20.72 - proc3: finished  ping /n 05 ::1
12:24:20.72 - proc3: starting  ping /n 10 ::1
12:24:21.75 - proc4: finished  ping /n 15 ::1
12:24:21.75 - proc4: starting  ping /n 15 ::1
12:24:26.82 - proc2: finished  ping /n 20 ::1
12:24:26.82 - proc2: starting  ping /n 07 ::1
12:24:29.86 - proc3: finished  ping /n 10 ::1
12:24:32.89 - proc2: finished  ping /n 07 ::1
12:24:35.92 - proc4: finished  ping /n 15 ::1
12:24:36.93 - proc1: finished  ping /n 20 ::1
Thats all folks!

/Oプロセス出力を表示するオプションを指定して実行した場合の出力は次のとおりです。

-------------------------------------------------------------------------------
12:24:51.02 - proc1: starting  ping /n 05 ::1
-------------------------------------------------------------------------------
12:24:51.02 - proc2: starting  ping /n 20 ::1
-------------------------------------------------------------------------------
12:24:51.03 - proc3: starting  ping /n 10 ::1
-------------------------------------------------------------------------------
12:24:51.04 - proc4: starting  ping /n 15 ::1
===============================================================================
12:24:55.10 - proc1: finished  ping /n 05 ::1

Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms

Ping statistics for ::1:
    Packets: Sent = 5, Received = 5, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:24:55.10 - proc1: starting  ping /n 07 ::1
===============================================================================
12:25:00.17 - proc3: finished  ping /n 10 ::1

Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms

Ping statistics for ::1:
    Packets: Sent = 10, Received = 10, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:25:00.19 - proc3: starting  ping /n 05 ::1
===============================================================================
12:25:01.22 - proc1: finished  ping /n 07 ::1

Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms

Ping statistics for ::1:
    Packets: Sent = 7, Received = 7, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:25:01.23 - proc1: starting  ping /n 20 ::1
===============================================================================
12:25:04.27 - proc3: finished  ping /n 05 ::1

Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms

Ping statistics for ::1:
    Packets: Sent = 5, Received = 5, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:25:04.28 - proc3: starting  ping /n 10 ::1
===============================================================================
12:25:05.30 - proc4: finished  ping /n 15 ::1

Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms

Ping statistics for ::1:
    Packets: Sent = 15, Received = 15, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:25:05.32 - proc4: starting  ping /n 15 ::1
===============================================================================
12:25:10.38 - proc2: finished  ping /n 20 ::1

Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms

Ping statistics for ::1:
    Packets: Sent = 20, Received = 20, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms
-------------------------------------------------------------------------------
12:25:10.40 - proc2: starting  ping /n 07 ::1
===============================================================================
12:25:13.44 - proc3: finished  ping /n 10 ::1

Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms

Ping statistics for ::1:
    Packets: Sent = 10, Received = 10, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms
===============================================================================
12:25:16.48 - proc2: finished  ping /n 07 ::1

Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms

Ping statistics for ::1:
    Packets: Sent = 7, Received = 7, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms
===============================================================================
12:25:19.52 - proc4: finished  ping /n 15 ::1

Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms

Ping statistics for ::1:
    Packets: Sent = 15, Received = 15, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms
===============================================================================
12:25:20.54 - proc1: finished  ping /n 20 ::1

Pinging ::1 with 32 bytes of data:
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms
Reply from ::1: time<1ms

Ping statistics for ::1:
    Packets: Sent = 20, Received = 20, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms
===============================================================================
Thats all folks!
于 2012-07-30T04:33:30.487 に答える
23

試してくださいstart

start "title of the process" "P:\ath\to.exe"

指定されたタイトルで新しいウィンドウを開き、BAT、CMD、または EXE ファイルを実行します。優先順位を設定したり、同じ環境を設定したりすることもできます。

実行できないファイルは、関連するプログラムで開かれます。

さらに読む: 開始 -> 実行

cmd /k start /?

Start は、少なくとも WinME 以降で利用できます。

幸運を!

于 2009-03-24T09:32:41.377 に答える
20

Powershell 2 を使用したいように聞こえますが、を使用して新しいcmdウィンドウ (または他のプロセス) を生成できます。この回答startも参照してください。ただし、「プロセス プール」のようなものを作成するには、おそらく他のツールとちょっとしたトリックを使用する必要があります (一度に最大n 個のインスタンスのみを実行するため)。後者は、すでに存在する数 ( loop または、該当する場合) を使用してカウントし、単に待機 ( ) して、新しいプロセスを生成できるかどうかを再確認することで実現できます。tasklist /imforwcping -n 2 ::1 >nul 2>&1

このための小さなテスト バッチをまとめました。

@echo off
for /l %%i in (1,1,20) do call :loop %%i
goto :eof

:loop
call :checkinstances
if %INSTANCES% LSS 5 (
    rem just a dummy program that waits instead of doing useful stuff
    rem but suffices for now
    echo Starting processing instance for %1
    start /min wait.exe 5 sec
    goto :eof
)
rem wait a second, can be adjusted with -w (-n 2 because the first ping returns immediately;
rem otherwise just use an address that's unused and -n 1)
echo Waiting for instances to close ...
ping -n 2 ::1 >nul 2>&1
rem jump back to see whether we can spawn a new process now
goto loop
goto :eof

:checkinstances
rem this could probably be done better. But INSTANCES should contain the number of running instances afterwards.
for /f "usebackq" %%t in (`tasklist /fo csv /fi "imagename eq wait.exe"^|find /c /v ""`) do set INSTANCES=%%t
goto :eof

並行して最小化されて実行される最大 4 つの新しいプロセスが生成されます。各プロセスの実行量と実行時間に応じて、おそらく待機時間を調整する必要があります。何か他のことをしている場合は、おそらく tasklist が探しているプロセス名も調整する必要があります。

ただし、このバッチによって生成されたプロセスを正しくカウントする方法はありません。1 つの方法は、バッチ ( ) の開始時に乱数を作成%RANDOM%し、処理を行う (または処理プログラムを生成する) ヘルパー バッチを作成することですが、ウィンドウ タイトルをパラメーターに設定することができます。

@echo off
title %1
"%2" "%3"

これは、タイトルを最初のパラメーターに設定し、3 番目のパラメーターを引数として 2 番目のパラメーターを実行する単純なバッチです。次に、指定したウィンドウ タイトル ( ) を持つプロセスのみを選択することで、タスクリストをフィルター処理できますtasklist /fi "windowtitle eq ..."。これはかなり確実に機能し、誤検知が多すぎるのを防ぎます。ワーカー プロセスのプールが制限されるため、まだ実行中のインスタンスがいくつかある場合、を検索するcmd.exeことはお勧めできません。

%NUMBER_OF_PROCESSORS%スポーンするインスタンス数の適切なデフォルトを作成するために使用できます。

これを簡単に適応させてpsexec、プロセスをリモートで生成することもできます (ただし、バッチでパスワードを提供するだけでなく、他のマシンで管理者権限を持っている必要があるため、あまり実用的ではありません)。ただし、フィルタリングにはプロセス名を使用する必要があります。

于 2009-03-24T09:32:37.650 に答える
6

-P 並列処理オプションをサポートする基本的な Windows xargs-like-clone がhttp://www.pirosa.co.uk/demo/wxargs/wxargs.htmlにあります。

于 2012-08-20T16:09:32.513 に答える
5

LinuxでのGNUxargsには、「n」プロセスを並行して起動するための「-Pn」スイッチがあります。

たぶん、xargsのcygwin / mingwビルドもこれをサポートしていますか?

次に、次を使用できます。

xargs -P 4 processFile < fileList

ただし、派手なマルチノードプロセスの生成はありません。

于 2009-03-28T20:47:08.590 に答える
1

マルチスレッドサポートを提供するライブラリを作成しました(スレッドプールの動作を「エミュレート」する方法で)

github の MultiBat

これがそのライブラリのインライン バージョンですが、最新バージョン (および、bat ファイルにインライン化する必要がないバージョン) については、上記のリンクにアクセスしてください。

REM ---------------------------------------------------------------------------
REM ---------------------------------------------------------------------------
REM ---------------------------------------------------------------------------
goto:EOF
REM Append this to the END of your batch-file [*.BAT] to get inline "Multi" support

REM  "Multi" is a thread-pool emulation helper library for controlling multi-threaded windows batch [*.BAT] files
REM  Copyright (c) 2020 Adisak Pochanayon
REM  Contact: adisak@gmail.com
REM  See Multi_License.txt for details

REM -----------------------------------

:Multi_Setup

call :Multi_SetName %1

if "%2"=="" (
    if "%NUMBER_OF_PROCESSORS%"=="" call :Multi_SetLimitToMax
) else (
    call :Multi_SetLimit %2
)
goto:EOF

REM -----------------------------------

:Multi_SetName
REM Returns: MULTI_CHILDPROC_WINNAME - name to use for child processes (the window title)

if "%1"=="" (
    SET MULTI_CHILDPROC_WINNAME=Multi-CmdProc
) else (
    SET MULTI_CHILDPROC_WINNAME=Multi-CmdProc-%1
)
goto:EOF

REM -----------------------------------

REM To Enable Hyperthreading, call Multi_SetHyperThread before calling Multi_Setup or Multi_SetLimitToMax

:Multi_SetHyperThread
REM Parameter 1: (optional)
REM        value=1    (or unspecified) - Use Hyperthreading if available
REM        value=0 (or other) - Do not use Hyperthreading to compute the max threads
REM Returns: NumberOfCores - number of real CPU cores
REM Returns: MULTI_HAS_HYPERTHREADING - 1 if the CPU has Hyperthreading
REM Returns: MULTI_USE_HYPERTHREADING - 1 if "Multi" should use Hyperthreading

REM Set variable NumberOfCores
if "%NumberOfCores%"=="" (
    for /f "tokens=*" %%f in ('wmic cpu get NumberOfCores /value ^| find "="') do set %%f
)

REM Set variable MULTI_HAS_HYPERTHREADING
if "%MULTI_HAS_HYPERTHREADING%"=="" (
    if "%NumberOfCores%"=="%NUMBER_OF_PROCESSORS%" (
        REM Non-Hyperthreading
        SET MULTI_HAS_HYPERTHREADING=0
    ) else (
        REM Hyperthreading
        SET MULTI_HAS_HYPERTHREADING=1
    )
}

if "%1"=="" (
    SET MULTI_USE_HYPERTHREADING=%MULTI_HAS_HYPERTHREADING%
) else (
    SET MULTI_USE_HYPERTHREADING=%1
)

REM Set the max threads to the limit (respecting Hyperthreading options)
call :Multi_SetLimitToMax
goto:EOF

REM -----------------------------------

:Multi_SetLimit
REM Parameter 1:
REM        value=N    - Use N as the number of max threads
REM        unspecified - Compute the default number of max threads
REM Returns: MULTI_MAXCHILDREN - the maximum number of child processes to run simultaneously

if "%1"=="" (
    if "%MULTI_MAXCHILDREN%"=="" call :Multi_SetLimitToMax
    goto:EOF
)

SET /A MULTI_MAXCHILDREN=%1
if %MULTI_MAXCHILDREN% LSS 1 SET MULTI_MAXCHILDREN=1
goto:EOF

REM -----------------------------------

:Multi_SetLimitToMax
REM Parameter 1: (optional)
REM        Passed to Multi_SetHyperThread if present
REM Returns: MULTI_MAXCHILDREN - max number of "threads" in pool for "Multi"

if "%1"=="" (
    REM Check if Hyperthreading support was initialized
    if "%NumberOfCores%"=="" (
        call :Multi_SetHyperThread 0
        REM Multi_SetHyperThread calls back to this subroutine so exit to prevent recursion
        goto:EOF
    )
) else (
    call :Multi_SetHyperThread %1
    REM Multi_SetHyperThread calls back to this subroutine so exit to prevent recursion
    goto:EOF
)

if %NUMBER_OF_PROCESSORS% LEQ 3 (
    SET MULTI_MAXCHILDREN=1
) else (
    if "%NumberOfCores%"=="%NUMBER_OF_PROCESSORS%" (
        REM Non-Hyperthreading
        SET /A MULTI_MAXCHILDREN=%NUMBER_OF_PROCESSORS%-2
    ) else if "%MULTI_USE_HYPERTHREADING%"=="1" (
        REM Hyperthreading available and used
        SET /A MULTI_MAXCHILDREN=%NUMBER_OF_PROCESSORS%/2 - 1
    ) else (
        REM Hyperthreading available but not used
        SET /A MULTI_MAXCHILDREN=%NUMBER_OF_PROCESSORS%-2
    )
)
goto:EOF

REM -----------------------------------

:Multi_RunWin

if "%MULTI_CHILDPROC_WINNAME%"=="" call :Multi_SetName

call :Multi_WaitChildrenMax
start "%MULTI_CHILDPROC_WINNAME%" /BELOWNORMAL cmd /c %*
goto:EOF

REM -----------------------------------

:Multi_RunWinMin

if "%MULTI_CHILDPROC_WINNAME%"=="" call :Multi_SetName

call :Multi_WaitChildrenMax
start "%MULTI_CHILDPROC_WINNAME%" /MIN /BELOWNORMAL cmd /c %*
goto:EOF

REM -----------------------------------

:Multi_RunSyncMin

REM Use this command to run things that mess with the window title
REM and otherwise would screw up the "Multi" System
start "Multi-Sync" /MIN /WAIT cmd /c %*
goto:EOF

REM -----------------------------------

:Multi_WaitChildrenMax

REM Wait until less than MULTI_MAXCHILDREN children are running

if "%MULTI_MAXCHILDREN%"=="" call :Multi_SetLimitToMax

call :Multi_WaitChildren %MULTI_MAXCHILDREN%
goto:EOF

REM -----------------------------------

:Multi_WaitChildren

SETLOCAL
REM multi_WAITCOUNT is a local variable
SET multi_WAITCOUNT=1

if "%1"=="" GOTO :loop_WaitChildren
SET /A multi_WAITCOUNT=%1
if %multi_WAITCOUNT% LSS 1 set multi_WAITCOUNT=1

:loop_WaitChildren
call :Multi_GetNumChildren
if %MULTI_NUM_CHILDREN% LSS %multi_WAITCOUNT% GOTO :exit_WaitChildren
timeout /t 1 /nobreak > nul
GOTO :loop_WaitChildren

:exit_WaitChildren
ENDLOCAL
goto:EOF

REM -----------------------------------

:Multi_GetNumChildren
REM Returns: MULTI_NUM_CHILDREN - the number of "children" processes (Windows named MULTI_CHILDPROC_WINNAME)

if "%MULTI_CHILDPROC_WINNAME%"=="" call :Multi_SetName

REM MULTI_NUM_CHILDREN should contain the number of 
REM running %MULTI_CHILDPROC_WINNAME% instances after this
for /f "usebackq" %%t in (`tasklist /fo csv /fi "WINDOWTITLE eq %MULTI_CHILDPROC_WINNAME%" ^| find /c "cmd"`) do (
    SET MULTI_NUM_CHILDREN=%%t
)
goto:EOF

REM -----------------------------------
于 2020-09-18T20:40:36.947 に答える