Batch: Taskkill timeout without waiting for timer - batch-file

I'm writing a batch script which runs a few programs. As each program finishes what it's doing it waits for either the user to close it out, moving on to the next, or being closed by taskkill after a timeout of so many seconds. If I consider the main script as MAIN, the program as TASK and the timer as KILLER. The MAIN starts the TASK and KILLER at (about) the same time. TASK does what it's supposed to and KILLER waits 600 seconds before killing TASK. However if TASK were closed by the user it should kill the KILLER and return to MAIN without user interaction. However using ping or timeout I still have to wait for the timer to expire before the batch will actually close. I would like not to have my desktop littered with command windows that'll do nothing. Is there any way around this?

You can use something like this
#echo off
setlocal enableextensions disabledelayedexpansion
start "" task.exe
call :timeoutProcess "task.exe" 300
start "" task.exe
call :timeoutProcess "task.exe" 300
exit /b
:timeoutProcess process timeout [leave]
rem process = name of process to monitor
rem timeout = timeout in seconds to wait for process to end
rem leave = 1 if process should not be killed on timeout
for /l %%t in (1 1 %~2) do (
timeout /t 1 >nul
tasklist | find /i "%~1" >nul || exit /b 0
)
if not "%~3"=="1" taskkill /f /im "%~1" >nul 2>nul
if %errorlevel% equ 128 ( exit /b 0 ) else ( exit /b 1 )
The timeout logic is moved to a subroutine that will wait until the process ends or the timeout is reached.

Here's a vbs script.
It waits till a program exits, see's if it's notepad, then restarts notepad if it is. Change Win32_ProcessStopTrace to Win32_ProcessStartTrace for program starts, or Win32_ProcessTrace for all starts and stops.
Console scripts are started like so. GUI scripts just execute the script direct. GUI scripts are invisible.
cscript "c:\somefolder\script.vbs"
To wait in a script use wscript.sleep 600000 (milliseconds).
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
Set objEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM Win32_ProcessStopTrace")
Do
Set objReceivedEvent = objEvents.NextEvent
wscript.echo objReceivedEvent.ProcessName
If lcase(objReceivedEvent.ProcessName) = lcase("Notepad.exe") then
WScript.echo "Process exited with exit code " & objReceivedEvent.ExitStatus
WshShell.Run "c:\Windows\notepad.exe", 1, false
End If
Loop
And this is how to start an invisible command window.
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "cmd /k dir c:\windows\*.*", 0, false

Related

Waiting for eight parallel batch scripts

I have like 0 experience with coding batch files and I'm actually refering to an older post
"Waiting for parallel batch scripts", and to the answer of dbenham.
#echo off
setlocal
set "lock=%temp%\wait%random%.lock"
:: Launch one and two asynchronously, with stream 9 redirected to a lock file.
:: The lock file will remain locked until the script ends.
start "" cmd /c 9>"%lock%1" one.bat
start "" cmd /c 9>"%lock%2" two.bat
:Wait for both scripts to finish (wait until lock files are no longer locked)
1>nul 2>nul ping /n 2 ::1
for %%N in (1 2) do (
( rem
) 9>"%lock%%%N" || goto :Wait
) 2>nul
::delete the lock files
del "%lock%*"
:: Launch three and four asynchronously
start "" cmd /c three.bat
start "" cmd /c four.bat
His answer works fine, but I would like to adapt his solution to run not 2 files simultaneously but 8, and after that another 8 and so on...
Can someone help me?
What I tried so far is this (for 3 blocks of 8 batch files each)
#echo off
setlocal
set "lock=%temp%\wait%random%.lock"
:: Launch 8 files asynchronously, with stream 9 redirected to a lock file.
:: The lock file will remain locked until the script ends.
start "" cmd /c 9>"%lock%1" one.bat
start "" cmd /c 9>"%lock%2" two.bat
start "" cmd /c 9>"%lock%3" three.bat
start "" cmd /c 9>"%lock%4" four.bat
start "" cmd /c 9>"%lock%5" five.bat
start "" cmd /c 9>"%lock%6" six.bat
start "" cmd /c 9>"%lock%7" seven.bat
start "" cmd /c 9>"%lock%8" eight.bat
:Wait for all scripts to finish (wait until lock files are no longer locked)
1>nul 2>nul ping /n 2 ::1
for %%N in (1 2 3 4 5 6 7 8) do (
( rem
) 9>"%lock%%%N" || goto :Wait
) 2>nul
::delete the lock files
del "%lock%*"
:: Launch 8 files asynchronously, with stream 9 redirected to a lock file.
:: The lock file will remain locked until the script ends.
start "" cmd /c 9>"%lock%1" nine.bat
start "" cmd /c 9>"%lock%2" ten.bat
start "" cmd /c 9>"%lock%3" eleven.bat
start "" cmd /c 9>"%lock%4" twelve.bat
start "" cmd /c 9>"%lock%5" thirteen.bat
start "" cmd /c 9>"%lock%6" fourteen.bat
start "" cmd /c 9>"%lock%7" fifteen.bat
start "" cmd /c 9>"%lock%8" sixteen.bat
:Wait for all scripts to finish (wait until lock files are no longer locked)
1>nul 2>nul ping /n 2 ::1
for %%N in (1 2 3 4 5 6 7 8) do (
( rem
) 9>"%lock%%%N" || goto :Wait
) 2>nul
::delete the lock files
del "%lock%*"
:: Launch three and four asynchronously
start "" cmd /c seventeen.bat
start "" cmd /c eighteen.bat
start "" cmd /c nineteen.bat
start "" cmd /c twenty.bat
start "" cmd /c twenty-one.bat
start "" cmd /c twenty-two.bat
start "" cmd /c twenty-three.bat
start "" cmd /c twenty-four.bat
But it doesn't seem to work right. Normaly a block of eight batch files will be completed after max. 3h but I waited almost 24h and he seems to be stuck in the first block...
Critical Info: When a batch file (or Job) is executed a "cmd" window opens for like 5 seconds, closes and an other programm starts which is doing the actual job of calculations for max. 3h. I looked into the Task Manager and what happens is, 3 processes are started. "standard.exe" and "eliT_DriverLM.exe" after like 20 sec and "python.exe" after 5 sec. Since the process is finished when this 3 processes are no longer running (not showing up in the Task Manager anymore), the programm should wait for the for at least the "standard.exe" to terminate.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q57071663.txt"
SET "lockfilename=%temp%\LOCK#_"
:: BLOCKSIZE - if positive, run in blocks of this size.
:: If negative, run max this number of parallel jobs
SET /a blocksize=-5
FOR /f "usebackqtokens=1*delims=|" %%a IN ("%filename1%") DO (
IF "%%b"=="" (SET "jobname="&SET "jobinstr=%%a") ELSE (SET "jobname=%%a"&SET "jobinstr=%%b")
CALL :sub
)
GOTO :EOF
:sub
SET /a absblocksize=blocksize
IF %blocksize% gtr 0 GOTO blockmode
SET /a absblocksize=-blocksize
:blockmode
FOR /L %%c IN (1,1,%absblocksize%) DO IF NOT EXIST "%lockfilename%_%%c" SET "lock=%lockfilename%_%%c"&GOTO release
:: No vacant spots, so block complete. Wait for ALL to finish
:blockwait
CALL :wait1
IF %blocksize% gtr 0 IF EXIST "%lockfilename%_*" (GOTO blockwait) ELSE (GOTO blockmode)
GOTO blockmode
:release
ECHO.>"%lock%"
START "%jobname%" CMD /c "call %jobinstr%&DEL "%lock%""
GOTO :eof
:wait1
timeout /t 1 >NUL 2>NUL
GOTO :eof
You would need to change the setting of sourcedir to suit your circumstances. The listing uses a setting that suits my system.
I used a file named q57071663.txt containing some dummy data for my testing.
%lockfile% is used temporarily and is a filename of your choosing.
The usebackq option is only required because I chose to add quotes around the source filename.
The contents of q57071663.txt are, for my demo,
Job 1 | q57071663_sub.bat 12
Job 2 | q57071663_sub.bat 4
Job 3 | q57071663_sub.bat 15
Job 4 | q57071663_sub.bat 2
Job 5 | q57071663_sub.bat
Job 6 | q57071663_sub.bat
Job 7 | q57071663_sub.bat
Job 8 | q57071663_sub.bat
Job 9 | q57071663_sub.bat 6
Job11 | q57071663_sub.bat 12
Job12 | q57071663_sub.bat 4
Job13 | q57071663_sub.bat 15
Job14 | q57071663_sub.bat 2
Job15 | q57071663_sub.bat
Job16 | q57071663_sub.bat
Job17 | q57071663_sub.bat
Job18 | q57071663_sub.bat
Job19 | q57071663_sub.bat 6
Each line is an optional job name, a separator (I chose |, obviously) and the command to be executed by start...
and q57071663_sub.bat is simply
#ECHO OFF
SETLOCAL
SET "delay=%1"
:: IF no delay defined, random 3..19 secs
IF NOT DEFINED delay SET /a delay=3+(%RANDOM% %% 17)
timeout /t %delay% >NUL 2>NUL
ie. delay for (argument) seconds, or 3 to 19 if no argument provided.
As for the main routine, the for/f splits each line from the file using the | separator, and assigns the two parts to jobname and jobinstr, then executes the subroutine :sub.
The subroutine calculates the absolute value of blocksize and looks for a missing lockfile. If it finds a lockfile missing in the range, lock gets the lock filename and release sets a lockfile and starts the job, appending an instruction to delete the lockfile when the job terminates.
if there are no vacant slots available, we wait. If blocksize is greater than 0, then we may proceed to the next block if there are no remaining lockfiles, otherwise we wait. If blocksize is negative, then we simply try again.
So - if blocksize is positive, this would run all of the jobs in the file n at a time, waiting until each block of n is finished before starting the next block. If blocksize is negative, then we run n jobs in parallel, starting the next job in the list when any job terminates. This runs n jobs at all times.
Complete revision in the light of comments and critical information now included in question.
It would appear that the actual requirement is that at most 8 instances of standard.exe are running in parallel.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q57071663_c.txt"
SET /a blocksize=5
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO (
SET "jobinstr=%%a"
CALL :sub
)
GOTO :EOF
:sub
:: Wait 30 secs (29 + 1) to ensure last-started job is active
timeout /t 5 >NUL 2>NUL
:delay1
timeout /t 1 >NUL 2>NUL
:: Count #times critical .exe is in tasklist
SET /a active=0
:: FOR /f %%c IN ('tasklist^|findstr /b "standard.exe"^|find /c "standard.exe"' ) DO SET active=%%c
FOR /f %%c IN ('tasklist/v^|findstr /b "cmd.exe"^|find /c "q57071663"' ) DO SET active=%%c
ECHO %active% instances active
IF %active% geq %blocksize% GOTO delay1
START "%jobinstr%" CMD /c "call %jobinstr%"
GOTO :eof
You would need to change the setting of sourcedir to suit your circumstances. The listing uses a setting that suits my system.
I used a file named q57071663_c.txt containing the same job-data as above, except that the job-name and delimiter are removed.
I used a blocksize of 5 for testing. In OP's application, substitute 8
So - read each line of job-instructions to %%a and thence to jobinstr and call the subroutine SUB.
First thing to do in sub is to wait 30 secs (I used 6 sec for my testing) - this is just to ensure that the last-started job has created its instance of standard.exe
Then count the active standard.exe instances. I've commented-out the line for standard.exe and left in my test command, which requires both cmd.exe and q57071663 to be on the same tasklist line to indicate an instance of interest.
If there are the required number of instances already active, delay 1 second and try again.
Otherwise, start the required job.

How to make a .bat file check for a program and relaunch if it isn't open, also restarting the program if it's been running for x amount of time?

This can be two separate .bat files if needed, but I would prefer if it's possible on one.
I need to run a certain program, but it sometimes crashes.
I have this for a .bat so far.
It works as far as resetting the program every hour, but it does crash sometimes in between restarts.
I'd like to just have a check, so it launches if the program isn't found.
Is that possible?
#echo off
:loop
start "xx" "xxpath"
timeout /t 3600 >null
taskkill /f /im "xx" >null
timeout /t 4 >null
goto loop
Here is a sample batch that can check if any instance of chrome.exe is running or not
If not, we start it !
#echo off
Color 0A
Set WaitTimeSeconds=20
Set App_Path=C:\Program Files\Google\Chrome\Application\chrome.exe
for %%i in (%App_Path%) do set App_Name=%%~nxi
Title Checking if any "%App_Name%" instance is running ...
:Loop
Rem Clear the screen
cls
Rem Kill any application that have a status equal to not responding !
Taskkill /f /fi "status eq not responding">nul 2>&1
Rem Check if any application instance is running ; if not we start it !
TASKLIST | FINDSTR %App_Name% || START "" "%App_Path%"
Timeout /t %WaitTimeSeconds% /nobreak>nul
Goto Loop

can I implement a kill switch into a .bat fork bomb?

I want to show a friend how big the impact of a fork bomb can be on performance, but without needing to restart the computer afterwards.
Assuming the following fork bomb:
%0|%0
Is there a way to add a kill switch to this which, with one button press, will stop all running copies of this file, stop any new from being created and hopefully save the machine? I'm not really familiar with the command prompt syntax, so I'm not sure.
Two ideas:
a) limit the depth your "bomb" is going to fork:
#echo off
set args=%*
if "%args%" EQU "" (set args=0) else set /a args=%args%+1
if %args% LSS 8 start /min thisfile.bat
(this will produce 2^9 -1 command windows, but only your main window is open.)
b) kill the cmd.exe process in the main batch file
#echo off
SET args=%*
:repeat
start /min thisfile.bat.bat some_arg
if "%args%" NEQ "" goto repeat
pause
taskkill /im cmd.exe
pressing any key in the initial batch file will instamntly kill all cmd windows currently open.
These solutions were tested with some restrictions, so if they work in a "hot" forkbomb, please let me know.
hope this helps.
EDIT:
c)implement a time switch in the original bat:
(still stops even if you can't get past pause)
#echo off
set args=%*
:repeat
start /min thisfile.bat some_arg
if "%args%" NEQ "" goto repeat
timeout /T 10
taskkill /im cmd.exe
or, using the smaller "bomb":
#echo off
set args=%*
if "%args%" NEQ "" (%0 some_arg|%0 some_arg) else start /min thisfile.bat some_arg
timeout /T 10
taskkill /im cmd.exe
If you're out to just show your friend fork bombs why not go for a silent but deadly approach? The fork bomb is in vbs, the cleanup is in batch.
Do note, the vbs fork bomb does nothing turning your pc off/on wont fix, it just floods your session proccess's.
The fork bomb:
Do until true = false
CreateObject("Wscript.Shell").Run Wscript.ScriptName
Loop
Source
Cleanup:
title=dontkillme
FOR /F "tokens=2 delims= " %%A IN ('TASKLIST /FI ^"WINDOWTITLE eq
dontkillme^" /NH') DO SET tid=%%A
echo %tid%
taskkill /F /IM cmd.exe /FI ^"PID ne %tid%^"
Source
If it runs in an accessible directory, you could try
IF EXIST kill.txt (exit /b) ELSE (%0|%0)
and make a file called kill.txt in the directory to stop the bomb.

After terminate the batch needs to delete a .lock file that has been create

Hello I am very new in this and I was able to run one instance of a batch file.
However, another file is being created called something.lock but the file is not been deleted by itself when I stop the batch or close it.
The new file create is the one that helps to have one instance running.
Can the new file ".lock " be deleted after I close the script with the "X" or because an user ended correctly with going to label end:
The code that I have is
:init
set "started="
2>nul (
9>"%~f0.lock" (
set "started=1"
call :start
)
)
#if defined started (
del "%~f0.lock"
) else (
cls
ECHO Only one instance is allowed
timeout /NOBREAK /T 3 >nul
cls
)
exit /b
:start
cd /d %~dp0
cls
:initial
pause >nul
You are misapplying the lock file. You are simply checking to see if the file exists, which means you must guarantee that the file is deleted upon batch termination.
There is a much better way, which you have only partially implemented. Only one process can have the file open for write access. You just need to determine if the file is already locked by another process.
Once the process with the exclusive lock terminates, the lock will be released. This is true no matter how the script terminates - even if it was the result of Ctrl-C or window closure. The file might not be deleted, but the next time the script runs, the file won't be locked, so the script will proceed nicely.
In the code below I save the current definition of stderr to an unused file handle before I redirect sterr to nul. Within the inner block I redirect stderr back to the saved definition. In this way I prevent the error message if the file is already locked, but the CALLed :start routine will still print out error messages normally.
#echo off
:init
8>&2 2>nul ( 2>&8 9>"%~f0.lock" call :start ) || (
cls
ECHO Only one instance is allowed
timeout /NOBREAK /T 3 >nul
cls
)
del "%~f0.lock" 2>nul
exit /b
:start
cd /d %~dp0
cls
del asdfasdfasdf
:initial
pause >nul
The difficulty is that your batch thread itself won't have its own PID. There's no graceful way to tell whether your batch script is running or when it has terminated. And there's no way to wake the dead, to let the script have the last word when a user red X's or Ctrl+C's. When it's over, it's over.
There are a few ways you can do what you want to do. Try them all and see which you prefer. Use dbenham's solution. His is correct. The following efforts are left here as an exercise in futility, although Solution 4 seems to work very well. In the end, it's still just a hack; whereas dbenham's redirection sleight-of-hand provides a correct implementation of lock files the way lock files are supposed to work.
...
Solution 1
One simple way is to use powershell to minimize the current window, re-launch your script with start /wait, then after completion call powershell again to restore.
#echo off
setlocal
set "lock=%temp%\~%~n0.lock"
if "%~1" neq "wrapped" (
if exist "%lock%" (
echo Only one instance is allowed.
timeout /nobreak /t 3 >NUL
exit /b
)
rem :: create lock file
>"%lock%" echo 1
rem :: minimize this console
powershell -windowstyle minimized -command ""
rem :: relaunch self with "wrapped" argument and wait for completion
start /wait "" cmd /c "%~f0" wrapped
rem :: delete lock file
del "%lock%"
rem :: restore window
powershell -windowstyle normal -command ""
goto :EOF
)
:: Main script goes here.
:loop
cls
echo Simulating script execution...
ping -n 2 0.0.0.0 >NUL
goto loop
This should be enough for casual use and should account for any cause of the batch file's termination short of taskkill /im "cmd.exe" /f or a reboot or power outage.
Solution 2
If you need a more bulletproof solution, you can get the current console window's PID and intermittently test that it still exists. start /min a helper window to watch for its parent window to die, then delete the lock file. And as long as you're creating a watcher anyway, might as well let that watcher be the lock file.
Biggest drawback to this method is that it requires to end your main script with exit to destroy the console window, whether you want it destroyed or not. There's also a second or two pause while the script figures out its parent's PID.
(Save this with a .bat extension and run it as you would any other batch script.)
#if (#a==#b) #end /* JScript multiline comment
:: begin batch portion
#echo off
setlocal
:: locker will be a batch script to act as a .lock file
set "locker=%temp%\~%~nx0"
:: If lock file already exists
if exist "%locker%" (
tasklist /v | find "cleanup helper" >NUL && (
echo Only one instance allowed.
timeout /nobreak /t 3 >NUL
exit /b
)
)
:: get PID of current cmd console window
for /f "delims=" %%I in ('cscript /nologo /e:Jscript "%~f0"') do (
set "PID=%%I"
)
:: Create and run lock bat.
>"%locker%" echo #echo off
>>"%locker%" echo setlocal
>>"%locker%" echo echo Waiting for parent script to finish...
>>"%locker%" echo :begin
>>"%locker%" echo ping -n 2 0.0.0.0^>NUL
>>"%locker%" echo tasklist /fi "PID eq %PID%" ^| find "%PID%" ^>NUL ^&^& ^(
>>"%locker%" echo goto begin
>>"%locker%" echo ^) ^|^| ^(
>>"%locker%" echo del /q "%locker%" ^&^& exit
>>"%locker%" echo ^)
:: Launch cleanup watcher to catch ^C
start /min "%~nx0 cleanup helper" "%locker%"
:: ==================
:: Rest of script
:: blah
:: blah
:: blah
:: ==================
:end
echo Press any key to close this window.
pause >NUL
exit
:: end batch portion / begin JScript
:: https://stackoverflow.com/a/27514649/1683264
:: */
var oShell = WSH.CreateObject('wscript.shell'),
johnConnor = oShell.Exec('%comspec% /k #echo;');
// returns PID of the direct child of explorer.exe
function getTopPID(PID, child) {
var proc = GetObject("winmgmts:Win32_Process=" + PID);
return (proc.name == 'explorer.exe') ? child : getTopPID(proc.ParentProcessID, PID);
}
var PID = getTopPID(johnConnor.ProcessID);
johnConnor.Terminate();
// output PID of console window
WSH.Echo(PID);
Solution 3
You can also test a lock file and see whether it's stale by setting a timestamp within the lock file, and setting that same timestamp in your console window title. Only problem with this is that the window title doesn't revert to normal if the user terminates with Ctrl+C, so you can't run the script twice without closing the cmd window. But closing the window and opening a new one for subsequent launches may not be too terrible a price to pay, as this is the simplest method described thusfar.
#echo off
setlocal
set "started=%time%"
set "lockfile=%temp%\~%~n0.lock"
if exist "%lockfile%" (
<"%lockfile%" set /P "locktime="
) else (
set "locktime=%started%"
)
tasklist /v | find "%locktime%" >NUL && (
echo Only one instance allowed.
timeout /nobreak /t 3 >NUL
exit /b
)
title %~nx0 started at %started%
>"%lockfile%" echo %started%
:: rest of script here
echo Simulating script execution...
:loop
ping -n 2 0.0.0.0 >NUL
goto loop
Solution 4
Here's a bit more polished solution, combining methods 1 and 3. It re-launches itself in the same window, then sets the window title to a unique ID. When the script exits gracefully, the lock file is deleted. Whether the script exits gracefully or forcefully, the window title reverts back to its default. And if no window exists in the task list with a title matching the unique ID, the lock file is deemed stale and is overwritten. Otherwise, the script notifies the user that only one instance is allowed and exits. This is my favorite solution.
#echo off
setlocal
if "%~1" neq "wrapped" (
cmd /c "%~f0" wrapped %*
goto :EOF
)
:: remove "wrapped" first argument
shift /1
:: generate unique ID string
>"%temp%\~%~n0.a" echo %date% %time%
>NUL certutil -encode "%temp%\~%~n0.a" "%temp%\~%~n0.b"
for /f "usebackq EOL=- delims==" %%I in ("%temp%\~%~n0.b") do set "running_id=%%I"
del "%temp%\~%~n0.a" "%temp%\~%~n0.b"
set "lockfile=%temp%\~%~n0.lock"
if exist "%lockfile%" (
<"%lockfile%" set /P "lock_id="
) else (
set "lock_id=%running_id%"
)
tasklist /v | find "%lock_id%" >NUL && (
echo Only one instance allowed.
timeout /nobreak /t 3 >NUL
exit /b
)
title %running_id%
>"%lockfile%" echo %running_id%
:: rest of script here
echo Press any key to exit gracefully, or Ctrl+C to break
pause >NUL
del "%lockfile%"
goto :EOF

Waiting for parallel batch scripts

I have 4 batch files. I want to run one.bat and two.bat at once, concurrently. After completion of these two batch files, three.bat and four.bat should run at once, in parallel. I tried with many ways but mot works fine.
Can anyone help me over this?
This is easily done using a much simplified version of a solution I provided for Parallel execution of shell processes. Refer to that solution for an explanation of how the file locking works.
#echo off
setlocal
set "lock=%temp%\wait%random%.lock"
:: Launch one and two asynchronously, with stream 9 redirected to a lock file.
:: The lock file will remain locked until the script ends.
start "" cmd /c 9>"%lock%1" one.bat
start "" cmd /c 9>"%lock%2" two.bat
:Wait for both scripts to finish (wait until lock files are no longer locked)
1>nul 2>nul ping /n 2 ::1
for %%N in (1 2) do (
( rem
) 9>"%lock%%%N" || goto :Wait
) 2>nul
::delete the lock files
del "%lock%*"
:: Launch three and four asynchronously
start "" cmd /c three.bat
start "" cmd /c four.bat
I had this same dilemma. Here's the way I solved this issue.
I used the Tasklist command to monitor whether the process is still running or not:
:Loop
tasklist /fi "IMAGENAME eq <AAA>" /fi "Windowtitle eq <BBB>"|findstr /i /C:"<CCC>" >nul && (
timeout /t 3
GOTO :Loop
)
echo one.bat has stopped
pause
You'll need to tweak the
<AAA>, <BBB>, <CCC>
values in the script so that it's correctly filtering for your process.
Hope that helps.
Create a master.bat file that starts one.bat and two.bat. When one.bat and two.bat end correctly, they echo to file they have finished
if errorlevel 0 echo ok>c:\temp\OKONE
if errorlevel 0 echo ok>c:\temp\OKTWO
Then the master.bat wait for the existence of the two files
del c:\temp\OKONE
del c:\temp\OKTWO
start one.bat
start two.bat
:waitloop
if not exist c:\temp\OKONE (
sleep 5
goto waitloop
)
if not exist c:\temp\OKTWO (
sleep 5
goto waitloop
)
start three.bat
start four.bat
Another way is to try with the /WAIT flag
start /WAIT one.bat
start /WAIT two.bat
but you don't have any control on errors.
Here's some references
http://malektips.com/xp_dos_0002.html
http://ss64.com/nt/sleep.html
http://ss64.com/nt/start.html
Just adding another way, maybe the shortest.
(one.cmd | two.cmd) && (three.cmd | four.cmd)
Concept is really straight forward. Start one and 2 in paralel, once done and errorlevel is 0 run three and four.

Resources