Reputation: 6042
I'm facing a quite stupid problem. I have a list of commands generated by a NAnt script. These are stored in a bat file. In each line I'm calling an exe with several parameters. The exe operates on a set of files and modifies them. The set of files is always the same. We are talking about ~1000 calls of the exe so if each time a new console would pop up I'd get performance issues. "No problem" I thought and added START /B
to each command line so now the exe is started in background which works way faster.
Now here's the problem: As I've mentioned, the exe operates on the same set of files so sometimes it happens that a file can't be modified because it's already opened by a different instance of the program which results in a crash. I'd like to add the /W
parameter to each call to ensure that never two instances run at the same time. But this somehow disables the /B
parameter.
So my question is: is it possible to have my exe started in background AND force my batch to wait for each instance to terminate?
Please don't tell me that this is ugly. I know but I can't change anything about the setup. My company has been working with this s*** for years and the only point where I can make modifications is the generated bat file.
Here is the code of the generated bat:
start /B /W S:\ome\path\to\my\exe.exe --param1 --param2 "XYZ" --param3 "ZYX" --param4 "1 2 3" --param5 "321" --param6 "1337" --param7
start /B /W S:\ome\path\to\my\exe.exe --param1 --param2 "XYZ" --param3 "ZYX" --param4 "1 2 3" --param5 "321" --param6 "1337" --param7
start /B /W S:\ome\path\to\my\exe.exe --param1 --param2 "XYZ" --param3 "ZYX" --param4 "1 2 3" --param5 "321" --param6 "1337" --param7
...
start /B /W S:\ome\path\to\my\exe.exe --param1 --param2 "XYZ" --param3 "ZYX" --param4 "1 2 3" --param5 "321" --param6 "1337" --param7
start /B /W S:\ome\path\to\my\exe.exe --param1 --param2 "XYZ" --param3 "ZYX" --param4 "1 2 3" --param5 "321" --param6 "1337" --param7
start /B /W S:\ome\path\to\my\exe.exe --param1 --param2 "XYZ" --param3 "ZYX" --param4 "1 2 3" --param5 "321" --param6 "1337" --param7
Upvotes: 3
Views: 14766
Reputation: 82267
You can use start /b
without /wait
and build your own synchronizing.
This waits until the file lock.tmp
is no longer locked by the start
command.
This example uses calc.exe for demonstration.
It can be useful to use the ping command to wait a second, as without ping the cpu usage will go up to 100%.
But my test says that the cpu is only at 5% while waiting.
@echo off
call :syncExecute
call :syncExecute
call :syncExecute
exit /b
:::::::::::::
:syncExecute
( start /b c:\Windows\System32\calc.exe ) > lock.tmp
:waitForExit
(
REM ping -n 2 localhost > nul
echo dummy > lock.tmp
) 2> nul || goto :waitForExit
exit /b
EDIT: Solution with direct waiting
This uses the fact that a pipe will block until the producer is finished.
This solution doesn't needs extra cpu performance in a waiting loop and it can start the next job immediately after a job is finished.
@echo off
call :syncExecute
call :syncExecute
call :syncExecute
exit /b
:::::::::::::
:syncExecute
( start /b c:\Windows\System32\calc.exe ) | more > nul
exit /b
Upvotes: 6
Reputation: 67216
You may use a file as a flag to detect that the .exe file is running. Create the flag file before each execution of the .exe and remove it when the .exe ends. This way, the Batch file just needs to wait for the flag file to disappear before start the next .exe:
echo X > flag.txt
start "" /B "S:\ome\path\to\my\exe.exe --param1 ... --param7 & del flag.txt"
call :waitForProcess
echo X > flag.txt
start "" /B "S:\ome\path\to\my\exe.exe --param1 ... --param7 & del flag.txt"
call :waitForProcess
...
echo X > flag.txt
start "" /B "S:\ome\path\to\my\exe.exe --param1 ... --param7 & del flag.txt"
call :waitForProcess
echo X > flag.txt
start "" /B "S:\ome\path\to\my\exe.exe --param1 ... --param7 & del flag.txt"
call :waitForProcess
goto :EOF
:waitForProcess
ping -n 2 localhost > NUL
if exist flag.txt goto waitForProcess
exit /B
For better performance, you may adjust the ping
waiting time in :waitForProcess
subroutine so it waits approximately the same time that the .exe takes to end. If the .exe takes just milliseconds, you may entirely omit the ping
command.
Upvotes: 1
Reputation: 67216
Excuse me, I think there is a confusion here.
START
command is used to run more than one instance of a given program in parallel (asynchronous way) with other instances of the same program. When START
command is used with the /Wait switch, then the final result is the same as if the START
command is entirely omitted. The commands placed in a Batch file are executed in sequential way: the next one starts until the previous one ends. This is the same result you get if you execute the same commands without START /W
.
I think you will solve your problem if you omit the start /B /W
part in the commands stored in the generated Batch file. The execution of the .exe file should not open a new cmd.exe window, but if it does that, then the start
command have not a way to avoid that behaviour! Could you give us more details about this point?
Upvotes: 0