简体   繁体   中英

Can't run multiple batch files sequentially from master batch file in Win7

I have a bunch of batch files that each start a bunch of executables to run concurrently. Each batch file starts 30 executables. When those 30 are done, I want the next batch of executables to run, again 30 at a time. The .exe's are called using the "start" command in the batch files and they work just fine - I can run the individual batch files for each group of 30 exe's and they run concurrently like they should.

I have created a "master" batch file that calls each sub-batch file but I can't figure out how to get it to run the sub-batch files in sequence, waiting for one to finish before starting the next.

If the master batch file is like this:

Batch1.bat
Batch2.bat
Batch3.bat

then only the first batch file is called - the others are never called.

If the master batch file is like this:

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

then all of the sub-batch files start running at the same time and I get hundreds of executables trying to start up at the same time.

How do I make the master batch file call the first batch file, wait for it to finish, then call the next, wait for it to finish, then call the next, etc?

Thanks in advance,

rgames

When starting another batch CALL will start it in the same window and the called batch has access to the same variable context. So it can also change variables which affects the caller.

Using wait in your batch file to call the executable will wait for them to exit before.

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

Hope this helps

Excuse me. I think there is a misunderstanding here. If your master Batch file is this:

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

then the Batch2.bat is called after Batch1.bat ends, and so on. You may do a small test to confirm this. On the other side, is possible that each BatchN.bat program uses the same variables? If so, then the last values left from Batch1.bat may interfere with Batch2.bat, and so on. In this case, you must add a Setlocal command at beginning of each Batch file.

I had to run a data export program for several files. My solution:

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

It may be adapted to run programs other problems.

You will have to create a signaling mechanism to aware EXE completation.

I would create a third level batch to run each EXE, creating a temp file before executing EXE and deleting it after.

In sub-batch I would wait until there were no more temp files.

So, initial batch:

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

Sub-batch:

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

Finally, 3rd level batch, Batch_3rd.BAT:

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

%* are arguments passed from sub-batch (exe+arguments), %Index% is correct as start copies environment from sub-batch upon creation, and sub-batch don't change this copy. One final note: you can probably merge all batches into a single batch file, calling it recursively.

My solution:

1) I have four batch files: Parent.bat and Batch1.bat, Batch2.bat, Batch3.bat

2) Parent.bat contains the below lines (take a close note):

call Batch1.bat > result1.log

call Batch2.bat > result2.log

call Batch3.bat > result3.log

3) Make sure "into the end of Each Child batch file", you have an echo statement. After this echo statement there shouldn't be any code...

Say content of Batch1.bat file is:

echo begin

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

echo end

echo this_is_the_last_line

Just for testing, i will use simple sub-batches like (all of them are the same)

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

And a master batch file

@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

This code starts each of the sub-batches with an active redirection (user available stream 9 is used) to a temporary flag file. This will lock the flag file until all the processes started from sub-batches have ended as the redirection is inherited during the process creation.

All we have to do is to keep trying start the next batch file with the same redirection:

  • If the file is still locked (processes are running), the batch file can not be started, wait 5 seconds and retry again

  • If the file is not locked, the redirection can be created and the next batch file is started.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM