How to set a timeout for a process under Windows 7? - batch-file

I would like to start a program with a windows batch file. But the program should stop after a certain timeout value. For example: Run the program 60 seconds and stop it after 60 seconds.
Under Linux, there is this nice timeout command to do what I want. Windows has also a timeout command, but its just to pause a command, to delay its execution. Is there something else under Windows to do so ?
Setup: Windows 7, 64 Bit, Professional

start yourprogram.exe
timeout /t 60
taskkill /im yourprogram.exe /f

Bali C gave a concise and to the point answer.
I needed something a little more featureful and reusable.
Based on Bali C's Example. I came up with this.
If anyone should need the same as me.
your.bat
REM...
CALL STARTwaitKILL..bat /relative/path/your_program.exe
REM...
STARTwaitKILL.BAT
#ECHO OFF
IF[%1]==[] GOTO EOF
IF NOT EXIST %1 GOTO EOF
REM SET PRIORITY=/NORMAL
REM ADJUST PRIORITY, BELOWNORMAL LETS BATCH FILE RUN MORE SMOOTHLY
REM WITH A PROGRAM THAT CONSUMES MORE CPU. SEE ABOUT MAXWAIT BELLOW
SET PRIORITY=/BELOWNORMAL
REM SET PRIORITY=/LOW
REM 0 NORMAL WINDOW :: 1 NO WINDOW :: 2 MINIMIZED WINDOW
SET /A HIDDEN=1
REM MAXWAIT HERE IS MORE LIKE MINIMUM WAIT IN WINDOWS.
SET MAXWAIT=10
SET WAITCOUNT=0
SET ARGS=/I %PRIORITY%
IF %HIDDEN% EQU 1 SET ARGS=%ARGS% /B
IF %HIDDEN% EQU 2 SET ARGS=%ARGS% /MIN
START %ARGS% %1
:WAIT
IF %WAITCOUNT% GEQ %MAXWAIT% GOTO KILL_IT
TIMEOUT /T 1 > NUL
SET /A WAITCOUNT+=1
FOR /F "delims=" %%a IN ('TASKLIST ^| FIND /C "%~nx1"') DO IF %%a EQU 0 GOTO RUN_DONE
GOTO WAIT
:KILL_IT
TASKKILL /IM %~nx1 /F > NUL
:RUN_DONE
Could be fleshed out ore to take more arguments for priority and such, but I don't have the need for it. Shouldn't be hard to add.

Don't exist any command in Windows to delay an app or to set a timeout for an app
Timeout in Windows is for Delay the execution process of CMD/Batfile, nothing more utility.
You can use external tools for that, I don't remember the name of any now, so many underground software, sorry, but I remember that in the autoit official forum exists a similar commandline tool to launch an app setting the timeout,
and maybe in the tool NIRCMD, or ps2exec, check their help files, or someone inside the WAIK Kits.
This is the only you can do:
#Echo OFF
:: First launch the app in background mode, because some applications stops the execution of CMD.
Start /B ".\Dir\Your app.exe"
:: Then stay in background for a certain time
Timeout /T "Seconds"
:: Continue your code...
Pause&Exit

The start+timeout+taskkill waits exactly the given time. Since I needed to stop waiting if the process exits earlier, I created my own solution in C++.
The tuxliketimeout program mimics the GNU timeout. Feel free to download&compile from
https://github.com/cernoch/tuxliketimeout

In windows 10 the easiest way is with scriptrunner:
Demonstrate the timeout by running a pause command (this will kill the called process):
ScriptRunner.exe -appvscript cmd "/c" "pause" -appvscriptrunnerparameters -wait -timeout=20

Related

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

Batch - How To Run Two Commands At The Same Time?

I think someone asked a similar questions ,but mine is a bit different. I have this code:
#echo off
title Game
set time=1 am
timeout 10 /nobreak >nul & goto game
set time=2 am
:game
How can I make the
timeout 5 /nobreak >nul
and
goto game
work at the same time? This is how I want it to work if you still didn't get it:
The timeout starts and you play the game after the timeout ends it changes the time to 2 am. How can I do that at the same time and play the game without getting disturbed? Please help. Thanks!
No, Bob. 'tis you who doesn't get the point about the variable time. It is a reserved variable which is set by the system, but can be overridden by a user script. Virtually any other variable name, you can use - just not time, date, path, random and a few others.
As to your problem,
set "mytime=1 am"
call :starttimer
:game
... whatever
:getinput
set "response="
set /p "response=%~1"
if not exist timerfinished.txt goto :eof
:: here change "mytime"
set "mytime=2 am"
:starttimer
start /min "" timer.bat 10
goto :eof
where timer.bat is
#echo off
del timerfinished.txt 2>nul
timeout %1 /nobreak>nul
echo.>timerfinished.txt
exit
The timer.bat file simply deletes the flag-file timerfinished.txt, delays for the time set by the first parameter it receives (%1 - set to 10 in main code) then creates the file and exits.
The main code starts the timer initially using :starttimer then whenever you want to prompt-and-wait-for-a-response, you execute
call :getinput "Prompt for input "
and the response will appear in %response%.
Note that setting response to nothing initially in this routine ensures that the response is empty if the user simply presses Enter
OK - so nothing actually happens using this scheme until you enter a response, only then will the time be incremented and the game continues with an updated time. If you're expecting that the end of the timeout actually does something, really - that's not going to happen - unless you use choice to input your responses with the timeout option.
i think you are looking for a "game time", running faster than real time.
Best way: use another script to set a gametime variable (like below) in a separate (minimized) window. Whenever you need to access the current "gametime" in your main script, use <gametime.dat set /p "gametime="
GAMETIME.BAT:
#echo off
set gametime=10:00
for /f "tokens=1,2 delims=:" %%a in ("%gametime%") do (
set hours=%%a
set mins=%%b
)
:loop
call :increase_gametime
timeout 5 >nul
goto :loop
:increase_gametime
set /a mins+=10
set /a hours=hours+mins/60
set /a mins=mins%%60
set gametime=%hours%:%mins%
title %gametime%
>gametime.dat echo %hours%:%mins%

End a command after a given time in a bat file

I have a bat file to execute several programs, and there is a possibility that one program stays in a loop. And I would like to kill the execution of that program after 1 min and execute the next one.
The programs I would like to execute gif_0.exe, gif_1.exe, ... receiving inputs from txt and writing the output to another txt.
gif_0.exe input1.txt output1_0.txt
timeout /t 20
gif_0.exe input2.txt output2_0.txt
timeout /t 20
gif_1.exe input3.txt output3_0.txt
timeout /t 20
gif_2.exe input4.txt output4_0.txt
timeout /t 20
gif_3.exe input5.txt output5_0.txt
My idea is similar to Geisterfurz007.
But my batch starts the exe in parallel and also another instance of the batch with the name of the started exe as an arg. The new instance checks the arg and jumps to the sub where it waits for the timeout and tries to kill the exe.
#echo off
setlocal EnableDelayedExpansion
Set Wait=60
If "%1" Neq "" Goto :KillTask
for /l %%n in (0, 1, n) do (
set /a foo=%%n+1
start gif_%%n.exe input!foo!.txt output!foo!_0.txt
Start %~f0 gif_%%n.exe
)
Goto :Eof
:KillTask %1
timeout /t %Wait% /nobreak>nul
taskkill /F /IM %1
start "Title goes here" gif_0.exe input1.txt output1_0.txt
timeout /t 60 /nobreak>nul
taskkill /F /IM gif_0.exe
Should do the trick. Repeat after your needs.
Explanation:
starts your application with the given parameters
waits 60 seconds without the option to stop the timer before counting down and without any output.
Kills the task with the imagename of your application. If you may have several instances of this paralelly running this will kill all of them!
You can use filters to narrow down on one though; have a look at taskkill /?
I am not sure if there is a typo in your question but assuming your applications are gif_n.exe with the parameters inputn+1.exe outputn+1.exe
You can do the following:
#echo off
setlocal EnableDelayedExpansion
for /l %%n in (0, 1, n) do (
set /a foo=%%n+1
start gif_%%n.exe input!foo!.txt output!foo!_0.txt
timeout /t 60 /nobreak>nul
taskkill /F /IM gif_%%n.exe
)
This would go from 0 to n in single steps and would execute the same thing like above in a loop.
2 additions here:
The line setlocal EnableDelayedExpansion is needed to activate the possibility to use variables values after they were changed within a closed block of parenthesis like a for-loop or an if-condition.
set /a foo=%%n+1 will set the value of variable foo to the value of %%n+1. The switch /a is needed to perform an actual calculation and not the appending of a string.
To use the variable in our for-loop we have to use the DelayedExpasion (see above):
Simply change the % you would usually use to ! and you are done.
To make sure, everything works correctly you might want to place an echo in front of your three main lines.
Feel free to ask questions if something is unclear :)

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.

Run DOS Command for a Time Limit

I want to perform the following operations.
Read 1 word at a time from an input file consisting of many words.
Pass this word as an argument to another command line based application.
Run that application for a fixed amount of time, say 10 seconds.
Abort the execution of the application if it is still running after 10 seconds and go back, pick the next word from the input file and repeat steps 1 to 3.
Here is what I have written though it does not achieve exactly what I want it to:
#echo off
for /f %%i in ('type input.txt') do call:Routine %%i
:Routine
set app="myApp.exe"
set limit=60
%app% %1
goto Delay
:Delay
ping localhost -n %limit% > nul
The above script will introduce the delay after the execution of myApp has completed. However, I want it to run myApp.exe for not more than 10 seconds, if it does, then abort the application using taskkill and move on to the next word from the input file.
I searched for a solution online and came across this:
http://www.tech-archive.net/Archive/WinXP/microsoft.public.windowsxp.general/2006-04/msg03609.html
Though it does not answer my query exactly, I would like to make my code do something similar.
Thanks.
The logic in the linked code looks flawed: It either launches 3 download commands, or it delays ~59 seconds and attempts to kill all download commands, but it never does both. The TASKKILL command arguments are not correct - the imagename belongs after the /IM parameter.
In your code, you are not going to kill your task without the TASKKILL command!
You must GOTO :EOF or EXIT /B after your loop finishes, otherwise the code will fall through and execute the subroutine without using CALL. But there really is no need to use a subroutine at all.
You only need to initialize your variables once.
No need to execute a command in your IN() clause. FOR /F has a variation that can read the text file directly. Type HELP FOR from the command line and read the documentation carefully.
PING has roughly a 1 second delay between each echo request. So a count of 11 will yield a delay of roughly 10 seconds.
EDIT - originally forgot the critical START command to start the app in its own process
#echo off
set app="myApp.exe"
set limit=11
for /f %%i in (input.txt) do (
start "" %app% %%i
ping localhost -n %limit% > nul
taskkill /im %app% /f
)

Resources