1

I have a X.exe program that takes about 2-6 hours to finish. Exact time is unknown, but I'd like to implement a threshold of 6.5 or 7 hours. If this program does not return any value by this amount of time, it will be killed. How do I implement this using batch *.bat files?

Here is what I had so far: a timer bat1.bat and an actual bat2.bat.

bat1.bat:

start cmd /C bat2.bat & timeout /t 25200 & taskkill /im X.exe /f

bat2.bat:

cd blah
bat1.bat

The problem with this approach is that only after 25200 seconds (or 7 hours) the timer will be stopped, and it won't be terminated before that limit. How do I tell the computer that if the program X.exe is finished then don't wait anymore?

Any help is appreciated!

Squashman
  • 13,649
  • 5
  • 27
  • 36
kensaii
  • 314
  • 5
  • 16
  • 1
    If you set it up x.exe to run as a scheduled task you could tell it to stop the task after 8 hours. Unfortunately your only options in task scheduler is 1, 2, 4, 8 or 12 hours. What you could do though is use the `TASKLIST` command to check if the program is running every 300 seconds. If it is not running then the bat file can exit. If it is still running check how many seconds it is has run so far and kill it if it is 25,200 seconds. – Squashman Oct 21 '17 at 04:15
  • @Squashman thank you for the idea and command. I have a simple script `tasklist /fi "imagename eq X.exe"`, but how do you return the amount of time which `X.exe` has been running? can you provide a formal answer so that I can accept it also? thanks!!! – kensaii Oct 21 '17 at 20:44
  • 1
    Set three variables. %checktime% %elapsedtime% and %killtime%. Use the %checktime% variable with the `TIMEOUT` command. Then use the `TASKLIST` command to see if the process is running. If it is running add %checktime% to %elapsedtime%. Then check if %elapsedtime% is greater than or equal to %killtime%. If the kill time condition has not been met use the `GOTO` command to loop back to a label before the `TIMEOUT` command. If the kill time condition has been met then use the `TASKKILL` command to stop the process. – Squashman Oct 21 '17 at 22:33
  • @Squashman thanks alot, i think i figured it out according to your above comment. have a nice day! – kensaii Oct 22 '17 at 04:55

3 Answers3

3

I think this is a much simpler solution:

rem Start the process that will kill the X.exe program after 7 hours
start "WaitingToKill" cmd /C timeout /t 25200 ^& taskkill /im X.exe /f

rem Run the X.exe program and wait for it to terminate
X.exe

rem Kill the killer process and terminate
taskkill /fi "WINDOWTITLE eq WaitingToKill" /f

In this method there is not any additional code running at same time; just the waiting state of timeout command.

EDIT: Some explanations added

Note that both the "WaitingToKill" cmd.exe process with the timeout command and the X.exe program are running in parallel. If the timeout command ends after 7 hours, the taskkill /im X.exe /f command is executed, the X.exe program is killed and both cmd.exe processes ends.

If the X.exe program ends before the 7 hours, the Batch file execute the next line as usual. This line is taskkill /fi "WINDOWTITLE eq WaitingToKill" /f, so the window with the timeout command is killed and both cmd.exe processes ends.

Aacini
  • 65,180
  • 12
  • 72
  • 108
  • thanks for the answer, but that's why exactly the question is posed: `X.exe` sometimes finishes before the timer, hence i'd like to check periodically if the program is still running. the answer that you propose are almost identical with my former solution. am i mistaking somewhere? – kensaii Oct 23 '17 at 15:09
  • You don't need to periodically check anything: both processes must end when the other process ends, so it is only necessary to wait that one process ends and kill the other process at that time. See my edit... – Aacini Oct 23 '17 at 15:29
  • To be clearer: When kill `X.exe` program? when `timeout` command ends. When kill `timeout` command? when `X.exe` program ends (unless I misunderstood your requirement **`:/`**)... – Aacini Oct 23 '17 at 16:32
  • So? Did this much simpler solution worked correctly? – Aacini Oct 30 '17 at 17:17
  • +1. Nice idea! However `taskkill /fi "WINDOWTITLE eq WaitingToKill" /f` will not kill `timeout.exe` because it has no `Window Title`. May I suggest you to replace it by `taskkill /im cmd.exe /fi "WINDOWTITLE eq WaitingToKill" /f /t`. Also I have an idea to extend your solution, to not have a separate window for the *Killer* process which I can post as an alternate answer if you don't mind. – sst Jul 27 '18 at 11:03
0

thanks to @Squashman i was able to build a script on my own. seem to work fine

@echo off
setlocal enableextensions enabledelayedexpansion
set /a "checktime=60"
set /a "elapsedtime=0"
set /a "killtime=150"
set XProg=X.exe
start cmd /C runTest.bat 
timeout /t 10
:while1
    echo Go to WHILE loop.
    echo elapsedtime = %elapsedtime% 
    echo killtime = %killtime%
    set /a "timeleft = %killtime% - %elapsedtime%"
    echo timeleft = %timeleft%
    if /i %timeleft% geq 0 (
        tasklist /fi "imagename eq %XProg%" 2>NUL | find /i /n "%XProg%">NUL
        if "%ERRORLEVEL%"=="0" (
            echo %XProg% is still running...
        ) else (
            echo %XProg% is finished before timer.
        )
        set /a "elapsedtime = elapsedtime + checktime"
        timeout /t %checktime%
        goto :while1
    ) else (
        taskkill /im %XProg% /f
        echo %XProg% is terminated.
    )

lessons learned: 1. hard to compare numeric variables in batch (compare diff with 0 instead) 2. terminated first time elaspedtime > killtime (might be a bit longer than killtime depending how often it checks)

kensaii
  • 314
  • 5
  • 16
0

I've tried various solutions but in the end this is really cumbersome in batch. If you are willing to use an external tool the simplest way is

"C:\Program Files\Git\usr\bin\timeout.exe" 5 .\test.exe

It properly returns the exit code of the test process, also works if you spawn multiple test processes simultaneously and does not pop up windows all the time.

Trass3r
  • 5,858
  • 2
  • 30
  • 45