Loop batch file for X minutes? - batch-file

I am very new to batch files, having mostly coded in Matlab for years. I would simply like to loop some code I have written for a set number of minutes. In pseudocode:
While elapsedTime<timeLimit
Run Code
How do I declare the variables elapsedTime (which would be a time counter that runs throughout the While loop) and timeLimit (just a value in seconds)?

If you are using batch you could do this:
#echo off
set /p min=Set minutes:
set /a sec=%min% * 60
timeout %sec%

Calculating with time is difficult in batch (not impossible, just difficult).
Here is another approach: creating a dummy file, start an additional (independent) process which waits a certain time and then deletes the file.
The original process can loop until the file disappears:
#echo off
break> timer.tmp
start /min cmd /c "timeout 5 & del timer.tmp"
:loop
echo waiting...
timeout 1 >nul
if exist timer.tmp goto :loop
echo done waiting.
Just adapt the timeout to the desired time (5 seconds in my example)

Related

Can I slow down the speed of a batch file?

I am trying to write an ASCII movie in batch, and I need the script to echo a new line at about 10-15 lines per second (hopefully that's not too confusing). By default, the script goes insanely fast, making the whole thing more difficult to see.
What I would like to do is be able to set the execution speed of the batch file, and NOT the computer itself.
Here's an example of what I'd like:
#echo off
REM Below command sets script execution speed in lines per second
setspeed=10lps
REM Ten lines of 03 begin
echo The time is 13:20:03
echo The time is 13:20:03
echo The time is 13:20:03
echo The time is 13:20:03
echo The time is 13:20:03
echo The time is 13:20:03
echo The time is 13:20:03
echo The time is 13:20:03
echo The time is 13:20:03
REM Ten lines of 03 end
REM Ten lines of 04 begin
echo The time is 13:20:04
echo The time is 13:20:04
.....
Thanks!
Update: I found out that if you download NirCmd (link is at the bottom of the page), it includes a "wait" command that works quite well. In my batch script, I did this:
#echo off
::This tells NirCmd to wait for 5 seconds, and then proceed to the next command.
nircmd wait 5000
echo This is one line
nircmd wait 5000
echo This is another line
nircmd wait 5000
echo Oh, hey! Another line!
nircmd wait 5000
echo Take a guess what this is... Another line!
...
I like using choice commands. For instance:
#echo off
echo this is one line
choice /c q /d q /t 1 >nul
echo this is the second line
You can change the number after /t to set the seconds to wait. You can also press Q to skip the wait at any time.
In newer Windows OSes, there is the TIMEOUT command as well:
TIMEOUT /T 5
waits 5 seconds and displays a countdown like Waiting <countingDown> seconds. Proceed with any key.
TIMEOUT /T 5 > NUL
does the same without displaying anything.
TIMEOUT /T 5 /NOBREAK > NUL
additionally removes the possibility to speed up by pressing a key.
Bad thing: Only complete seconds possible, no millis.
TIMEOUT /T x > NUL
(replace the X with the number of seconds you want)
This will do a hidden countdown because of the > NUL command at the end you won't see the countdown/pause/sleep/timer and then it will proceed with the next command. This is the best to use, as I found the Timeout command with the NUL at the end to be the best many of the other commands like Sleep and Pause do not work.
You can also download NODEJS to get more functions or switch to powershell.
TIMEOUT /T 5 > NUL
Above command will give 5 second timed countdown with NO display, pressing any key will not stop it unless you use CTRL+C.

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 :)

Limit a batch file to only be able to run after 20 seconds after last run

I need to make a batch file that calls a URL (without opening a browser), but only after 20 seconds since previous run. If it's run sooner than 20 seconds, the script does nothing and closes. How would I go about doing this?
If your batchfile waits 20 seconds before closing, and you can only have one instance of it running at a time, then the problem is solved.
Use a technique like this or this to make your batch file exit ,without doing anything else, if it is already running.
Then, if the batchfile does not detect another instance running, Use the timeout command at the end of the batchfile to wait 20 seconds.
timeout /t 20
#montewhizdoh: if you add a timeout at the end of the batch file, it means you have to wait for 20 seconds before the batch actually returns, which may not be desirable, especially if the operations it performs are supposed to occur quickly.
#seventy70: by recording the current time in a separate file, you can ensure that the batch will exit without doing anything you don't want it to, unless a certain number of seconds has elapsed. The following code achieves this:
#echo off
Setlocal EnableDelayedExpansion
set lastTime=86500
if NOT EXIST lasttime.txt goto :nextStep
for /f "delims=;" %%i in (lasttime.txt) do (
set lastTime=%%i
)
set /A lastTime=(%lastTime:~0,2%*3600) + (%lastTime:~3,2%*60) + (%lastTime:~6,2%)
:nextStep
set currTime=%TIME%
set /A currTime=(%currTime:~0,2%*3600) + (%currTime:~3,2%*60) + (%currTime:~6,2%)
:: required check in case we run the batch file right before and right after midnight
if %currTime% LSS %lastTime% (
set /A spanTime=%lastTime%-%currTime%
) else (
set /A spanTime=%currTime%-%lastTime%
)
if %spanTime% LSS 20 (
echo Only %spantime% have passed since the last run
goto :eof
)
:: ************************************
:: DO ACTUAL STUFF HERE
:: ************************************
if exist lasttime.txt del lasttime.txt
echo %time%>>lasttime.txt
endlocal
So every time the batch is allowed to run, it records the current time in a file. The next time around, it reads the file, extracts the time from it and compares it with the current time. If less than 20 seconds have elapsed, the batch exits. If more than 20 seconds have passed, the actual operations can be executed and at the end, the current time is recorded again in the control file for use next time around.

Need batch for Netstat -anbo to run ever 30 minutes

Title description as stated. I'm very novice at this, so please go easy. I've searched articles here, and have tried several iterations of how to do this but my attempts have failed.
I need to run Netstat -anbo every 30 minutes to a text file and keep them rolling for at least 5 files.
Thanks.
Here's how you can run something every few secs in batch script, without the 'sleep' utility.. I will leave the implementation up to you :)
# :loop
REM "do something every 10 secs"
# ping localhost -n 11 > nul
# goto loop
The ping acts as a sleep here.. you can even ping to any non-existent host.
If you want a more accurate time interval, you are better off using
# :loop
REM Execute the MS-DOS dir command ever 20 seconds.
# SLEEP 20
# GOTO loop
For this to work, you will need to have a sleep MS-DOS utility on the computer. You can find it here
You would have to use a simple loop and timeout
A sample implementation
#echo off
:loop
netstat -anbo >> file.txt # >> Will append to file instead of erasing file content
timeout /t 1800 /nobreak # /t timeout in seconds /nobreak Ignore key presses and wait for specified time
goto :loop #Simple loop to keep batch running indefinitely
Remember to run this batch as administrator (For netstat)

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