Parallel execution of shell processes

前端 未结 6 613
没有蜡笔的小新
没有蜡笔的小新 2020-11-22 16:35

Is there a tool available to execute several process in parallel in a Windows batch file? I have found some interesting tools for Linux (parallel and PPSS), however, I would

相关标签:
6条回答
  • 2020-11-22 16:51

    Sounds more like you want to use Powershell 2. However, you can spawn new cmd windows (or other processes) by using start, see also this answer. Although you probably have to use some other tools and a little trickery to create something like a "process pool" (to have only a maximum of n instances running at a time). You could achieve the latter by using tasklist /im and counting how many are already there (for loop or wc, if applicable) and simply wait (ping -n 2 ::1 >nul 2>&1) and re-check again whether you can spawn a new process.

    I have cobbled together a little test batch for this:

    @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
    

    It spawns a maximum of four new processes that execute in parallel and minimized. Wait time needs to be adjusted probably, depending on how much each process does and how long it is running. You probably also need to adjust the process name for which tasklist is looking if you're doing something else.

    There is no way to properly count the processes that are spawned by this batch, though. One way would be to create a random number at the start of the batch (%RANDOM%) and create a helper batch that does the processing (or spawns the processing program) but which can set its window title to a parameter:

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

    This would be a simple batch that sets its title to the first parameter and then runs the second parameter with the third as argument. You can then filter in tasklist by selecting only processes with the specified window title (tasklist /fi "windowtitle eq ..."). This should work fairly reliable and prevents too many false positives. Searching for cmd.exe would be a bad idea if you still have some instances running, as that limits your pool of worker processes.

    You can use %NUMBER_OF_PROCESSORS% to create a sensible default of how many instances to spawn.

    You can also easily adapt this to use psexec to spawn the processes remotely (but wouldn't be very viable as you have to have admin privileges on the other machine as well as provide the password in the batch). You would have to use process names for filtering then, though.

    0 讨论(0)
  • 2020-11-22 16:57

    Try start:

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

    It opens a new window with the given title and executes the BAT, CMD or EXE file. You can also set the priority, set the same environment etc.

    Files being not executeable are opened with the associated program.

    Further reading: Start -> Run

    cmd /k start /?
    

    Start is available at least since WinME.

    Good luck!

    0 讨论(0)
  • 2020-11-22 16:59

    Edit - I modified the script to optionally display the output of each process

    Here is a native batch solution that reliably runs a list of commands in parallel, never launching more than n processes at a time.

    It even has a mechanism built in to distribute the processes to specific CPUs or remote machines via PSEXEC, but I haven't tested that feature.

    The trick to make this work is to START each command through a CMD process that redirects either stdout or an undefined handle to a lock file. The process will maintain an exclusive lock on the file until it terminates. It doesn't matter how the process terminates (normal exit, crash, killed process), the lock will be released as soon as it does.

    The master script can test if the process is still active by attempting to redirect to the same lock file. The redirection will fail if the process is still active, succeed if it has terminated.

    By default, the script ignores the output of each process. If started with the /O option as the 1st parameter, then it displays the output of each process, without interleaving.

    My demo sets the process limit to 4, and simply runs a series of PING commands of varying length.

    I've tested this on XP, Vista, and 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^^!
    

    Here is output from a sample run that ignores process output

    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!
    

    Here is the output if run with the /O option showing process output

    -------------------------------------------------------------------------------
    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!
    
    0 讨论(0)
  • 2020-11-22 17:08

    There is a basic Windows xargs-like-clone which does support the -P parallel processing option at http://www.pirosa.co.uk/demo/wxargs/wxargs.html

    0 讨论(0)
  • 2020-11-22 17:09

    GNU xargs under Linux has a "-P n" switch to launch "n" processes in parallel.

    Maybe cygwin/mingw build of xargs also supports this?

    Then you can use:

    xargs -P 4 processFile < fileList
    

    No fancy multi-node process spawning, though.

    0 讨论(0)
  • 2020-11-22 17:12

    I wrote a library which provides multithreading support (in a way that "emulates" the behavior of thread-pools)

    MultiBat on github

    Here is the inline version of that library but I'd suffest going to the link above for the latest version (and a version that doesn't require being inlined into your bat file.

    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 -----------------------------------
    
    0 讨论(0)
提交回复
热议问题