Question

There is a simple Windows batch file that runs multiple instances of application:

start app.exe param1
start app.exe param2

Is there a way to run them asynchronously at the same time (which above does) and wait for them both to finish to perform other actions - something like C#

Task.WhenAll(tasksList.ToArray());
/* Process tasksList.Result */

?
/wait switch will not help here, some polling for if particular instance is still running maybe.

Was it helpful?

Solution

I suppose this question is slightly different than Waiting for parallel batch scripts in that this application is waiting for .exe processes to finish instead of batch scripts. But the solution is nearly identical.

You must instantiate some form of polling in your master batch script. You can effectively create a lock file via redirection. The lock file remains locked until the process terminates. Your batch script polls, checking if it can open all the lock files. Once it succeeds, it knows all the processes have ended.

The only significant difference in the solution below is that START launches the .exe directly instead of launching a batch through CMD /C. I also learned that (call ) is an extremely fast way to effectively perform a no-op that always succeeds. So I substitued (call ) in place of rem

@echo off
setlocal
set "lock=%temp%\wait%random%.lock"

:: Launch processes asynchronously, with stream 9 redirected to a lock file.
:: The lock file will remain locked until the script ends.
start "" 9>"%lock%1" notepad.exe
start "" 9>"%lock%2" notepad.exe

:Wait for both processes to finish (wait until lock files are no longer locked)
1>nul 2>nul ping /n 2 ::1
for %%N in (1 2) do (
  (call ) 9>"%lock%%%N" || goto :Wait
) 2>nul

::delete the lock files
del "%lock%*"

:: Finish up
echo Done - ready to continue processing

See Parallel execution of shell processes for a pretty sophisticated application of the lock technique that regulates the maximum number of parallel processes, with the ability to direct processes to specific CPUs or machines via PSEXEC. That answer also provides a fuller explanation of exactly how the lock file technique works.


EDIT

The wait loop can be modified so that it does not need to change as you add more processes:

:Wait for all processes to finish (wait until lock files are no longer locked)
1>nul 2>nul ping /n 2 ::1
for %%F in ("%lock%*") do (
  (call ) 9>"%%F" || goto :Wait
) 2>nul

OTHER TIPS

Adapting on @dbenham answer, here's how i made it to work inside a for and for unlimited number of processes:

setlocal enabledelayedexpansion
for %%a in (*.*) do start "" 9>"%temp%/wait!random!.lock" /b /low "myprogram.exe" -program_parameters

:wait
ping /n 2 ::1 > nul
echo waiting processes to finish...
2>nul del "%temp%\wait*.lock" > nul
if exist "%temp%\wait*.lock" goto :wait

... more commands ...

Here %random% don't work, cause it's expanded when for is called, therefore making all numbers the same. So I enabledelayedexpansion and use !random!.

On the loop I try to delete all files. 2>nul will make sure any error won't show on screen. It will only go through when all can be deleted (if exist).

You are starting several instances of the same app.exe?

  • start them all
  • loop tasklist |find "app.exe" until %errorlevel% is 1
  • continue with your script

Powershell has more sophisticated ways to do it without wait loops. You can wrap or call your scripts with powershell and even implement your preferred managed solutions for doing it exactly as you do it in C#.

In a separate batch file asynchBatch.bat put:

start app.exe param1
start app.exe param2

Then in caller batch file write:

call asynchBatch.bat
other executions
...

The other executions will start only after both app.exe param1 and app.exe param2 finish.

Basically, you're doing it right using the START command becuase it is inteded for what you need now.

In addition, I would suggest you to refering to this great answer: https://stackoverflow.com/a/1449192/952310

UPDATE:

For waiting each program to finish, use the /W switch, look:

start /w app.exe param1
start /w app.exe param2
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top