Milliseconds (!) wait in Batch using no externals? - batch-file

I have searched intensively but have only found wait-tips in batch files in seconds units (the ping approach i.e.).
Since I have a need to wait in between two commands only for something like 10-100 milliseconds, that does not work for me unfortunately.
The wait-time needs not to be "super accurate". In my case, does not make a big difference if it's 10ms or 12/15ms, but it should be able to distinguish between 10 and, say 20.
I wonder if there is a solution, and if in any way possible, using just the windows "on board" commands / tricks as I want to have just the batch for ease of "installation" when using later on another machine.

#echo off
echo Time before: %time%
echo Wait %1 centiseconds (or more)
call :wait %1
echo Time after: %time%
goto :EOF
:wait centiseconds
for /F "tokens=3,4 delims=:." %%a in ("%time%") do set /A sec=1%%a, msec=1%%b+%1
if %msec% gtr 199 set /A sec+=1, msec-=100
set lim=%sec%%msec%
:waitHere
for /F "tokens=3,4 delims=:." %%a in ("%time%") do if 1%%a1%%b lss %lim% goto waitHere
exit /B
The minimum precise wait time entirely depends on the speed of the computer. For example, in my case a wait time less than 5 centiseconds always waits for more time. If I use a wait time from 5 centiseconds on, the timing is precise.
EDIT: I slightly modified the program in order to make it more precise with small wait times, it is now precise in my computer from 3 centiseconds on!
You must note that the minimum precise wait time also depends on the size of the Batch file; if the file is large, the minimum precise time increases...

You can use the %time% variable and calculate the difference.
In pseudo code it looks like this.
set startTime=%time%
:wait
set now=%time%
if now-startTime < waitTime goto wait
Btw externally programs will not work here, as the loading/starting time is not predictable and can be much longer as your waittime.

this might do, what you want:
#echo off
echo %time%
for /L %%i in (1,1,50) do ( echo %time% )>nul
echo %time%
for example three consecutive runs:
C:\>t
12:15:20,74
12:15:20,75
C:\>t
12:15:21,22
12:15:21,22
C:\>t
12:15:21,69
12:15:21,71
As you see, the first run gives you "about" 10ms, the second run gives you "about" 0ms, the third one gives you "about" 20ms.
Nothing reliable...
btw: if you replace echo %time% with echo time it's getting worse...

Related

Comparing User input variable to time command in batch

I'm trying to make a batch file that'll run in the background and shut my computer off when the regional time corresponds to a time I've set so that I can fix my sleep schedule.
However, I'm running into issues testing how to compare the current time to the time I've set as a variable.
I believe that it's due to the format that is returned by the time command and the format I entered not being the same.
I would like to enter a time in the 12-hour format and the computer shuts down at the designated time. But the time command returns a 24-hour format string unless paired with the /t switch.
This is what I currently have as test code that returns a printed line instead of shutting down my computer:
#echo off
set /p shutdownTime=What time would you like to shut down the computer?
:begin
set time=time /t
if "%time%" EQU "%shutdowmTime%" echo Time Confirmed
goto begin
I know that instead of an if statement in a loop I could probably do a for or while loop, but I'm honestly trying to keep it as simple as I can for my nocturnal smooth brain that woke up about 3 hours ago.
Any help is appreciated. Thank you.
Try this:
#echo off
FOR /F "tokens=* USEBACKQ" %%F IN (`time /t`) DO (
SET var=%%F
)
echo %var%
pause
will output 12hr time
#echo off
:resettime
echo make sure to Use caps for AM/PM and no spaces
set /p stime=What time would you like me to shutdown your computer?[example 03:45(AM/PM)]:
cls
echo your computer will shutdown at %stime%
:R
set /p p=would you like to change this time [y/n]:
if %p%==y goto resettime
if %p%==n goto loop
if not %p%==y goto R
if not %p%==n goto R
:loop
FOR /F "tokens=* USEBACKQ" %%F IN (`time /t`) DO (
SET var=%%F
)
set var=%var: =%
if %stime%==%var% goto endloop
goto loop
:endloop
shutdown /s
:a
set /p prompt=Would you like to abort shutdown [y/n]:
if %prompt%==y goto s
if not %prompt%==y goto a
:s
shutdown /a
I also quickly made the program described in your question. Its a bit buggy but it works.

Loop the command continuously (without pausing) for "X" seconds

Currently I am working on a batch file to execute a command continuously for X no. of seconds, and after elapse of X, I wish to redirect it using goto function.
This is the closest I have got to what I intend the code to do.
:MainMenu
set yourno=
set /p yourno=Input your number:
set /p looptime=Input time:
goto PerformCalc
:PerformCalc
set /a yourno= %yourno%+1
timeout 1
set /a looptime=%looptime%-1
goto CheckLoop
:CheckLoop
if %looptime% equ 0 goto FinishScreen
goto PerformCalc
:FinishScreen
echo Congratulations Your no. is %yourno%
echo Operations completed in %looptime% seconds
pause
Now the problem with the above code is if I set the loop time for 10 seconds, it will perform only 10 operations. But that is not something I intend to do. I realize that I have inputted timeout 1 in my code and reducing it by 1 everytime 1 second passes. However this is because I am unable to find a way to continuously loop the code for 10 seconds, without using timeout 1 thus pausing it to perform only 10 operations.
If you still do not get what I mean, here is the logical flow the code should perform (say for eg. the user inputs looptime as 10 seconds
For Time=10seconds
Do {set /a yourno= %yourno%+1 continuously}
After Time of 10 seconds has elapsed redirect to :FinishScreen
Thankyou for your help.
#echo off
setlocal
rem Get end time
set seconds=10
for /F "tokens=1-4 delims=:.," %%a in ("%time: =0%") do set /A "endTime=1%%a%%b%%c%%d+seconds*100"
echo Start: %time%
echo Working %seconds% seconds, please wait...
set yourNo=0
:loop
set /A yourNo+=1
rem Check if end time had been reached
for /F "tokens=1-4 delims=:.," %%a in ("%time: =0%") do if 1%%a%%b%%c%%d lss %endTime% goto loop
echo End: %time%
echo This program could complete %yourNo% loops in 10 seconds
This method may fail if the processing time pass over midnight, but a simple adjustment can solve this point, if needed...

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%

batch file label running for 30 seconds

I program to both learn how and to make fun files for jokes and tricks. I'm trying to make a batch file that will run a label inside the batch file for a set amount of time like 30 seconds without having to use a for-do statement. what I have so far is shown below and is reduced to a small test, but uses a for-do statement.
# echo off
for /l %%a in (1,1,10) do (
call :matrix)
echo Thanks for using the MATRIX
pause
:matrix
echo %random%%random%
use timeout command, it can set amount of time like 30 seconds without having to use a for-do statement.
# echo off
for /l %%a in (1,1,10) do (
call :matrix)
echo Thanks for using the MATRIX
timeout 30
:matrix
echo %random%%random%
if you don't want to show count done message, you can use timeout 30 >nul
this starts a second cmd process (minimized), that simply does a timeout 30. It's existence is the signal to repeat the loop.
#echo off
start /min "MyTimer" timeout 30
:loop
echo %random%%random%
tasklist /fi "windowtitle eq MyTimer" | find "Console" >nul && goto :loop
Sadly, tasklist doesn't give useful errorlevels, so we have to use find.
Note: for debugging purposes you may want to remove the start switch /min.

How to set a timeout for a process under Windows 7?

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

Resources