<

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x

Inserting Delays with Millisecond Resolution in Windows Batch (.bat) Files

Published on
19,625 Points
13,525 Views
1 Endorsement
Last Modified:
Approved
for /L %%a In (0 1 %number_of_pings%) do (
ping -n 1 -w 1.1.1.1 > nul
)

Open in new window

Inserting Delays with Millisecond Resolution in Windows Batch (.bat) Files
 
Occasionally, we want to write a Windows batch file or script in which we need to delay code execution. A good example is when we want to execute a number of PINGs in succession by using a code loop.

There are a few ways that this can be done and there is apparently a lot of misunderstanding due to the lack of complete documentation. So, I conducted some experiments and wrote some code that would both augment what we know about doing this and to suggest some ways to insert delays that are adjustable in increments of milliseconds.

Modern Windows systems have a timeout command that looks like this:

timeout n  where “n” is an integer number of seconds. 
So, clearly one can’t get delays that are adjusted to some number of milliseconds. There is also a sleep command that can be added that looks like this:

sleep n where “n” is also an integer number of seconds.
The most promising approach for millisecond-resolution delays seemed to be use of the PING command.

The PING timeout method uses a PING command to a non-existent IP address so that it has to wait to the end of its built-in or specified timeout period before finishing. And, the timeout period is specified in an integer number of milliseconds. So, it would appear to be a good mechanism to use for creating a delay with millisecond resolution. 

The first thing that I learned was that the PING timeout method doesn’t do what one might hope or think.
 
The General Approach using PING

The common PING command set up to create a delay looks like this;
PING –n 1 –w xxxxx [fake_IP_address] > nul

Open in new window


The “xxxxx” is the timeout entered as expressed in milliseconds.  So, one might think that “what you see is what you get”.  But that’s not the case.  After seeing some unexpected results, I decided to measure the timeout times.  Here’s the result:
  • If the timeout is 500 or less, 500 is the result.  The entry is ROUNDED UP to 500.
  • If the timeout is 999 of less, 500 is the result.  The entry is ROUNDED DOWN to 500.
  • If the timeout is 1000 or more, the timeout is ROUNDED DOWN to the nearest ½ second (500 milliseconds). For example, 1333 becomes 1000, 1999 becomes 1500, 2499 becomes 2000 and 2999 becomes 2500, etc. 
So, while the times are expressed in milliseconds, they are only effected in ½ second chunks. That could well be an unfortunate limitation for some.

A Trick for Using PING for Batch File millisecond Delays

If the timeout “-w” entry is omitted altogether, then the default timeout is 4000 milliseconds or 4 seconds.  (There is some unfortunate literature around that says it’s 1000 but that seems proven to be incorrect through good old-fashioned testing.)

Whether by a typo or some other insightful method, I discovered this (likely undocumented “feature”):

If the timeout in the PING command is blank, that is, if the command is structured with -w but with no parameter accompanying “–w” then it looks like this:
PING –n 1 –w  [fake_IP_address] > nul

Open in new window


Using this form of the PING command results in a very short timeout. I can only imagine that it’s machine dependent and I have to believe that it’s undocumented so one might only want to use it with some huge caveats:
  • You have to determine what the delay is going to be on the machine it’s to be used on.So, it’s likely not very “portable”.
  • You may have to be concerned about what the delay is going to be on a machine with other high-demand processes running.So, it may not be very accurate or stable.
Nonetheless, I figure it’s worth documenting and to make some suggestions regarding how to make use of it:

Let’s assume that we want a delay of 333 milliseconds. So that will be the objective of the batch file we’ll develop here. First, we need to know the single-ping delay. To get that number, we’ll run a little measurement batch program:
:LOOP
     ping 10.109.199.199 -n 1 -w >nul
     ping 10.109.199.199 -n 1 -w >nul
     [repeat the above PINGs 98 more times….] <--
echo %time%
GOTO :LOOP

Open in new window


After a very short time, you can pause this program by pressing CTRL+C.  And, don’t respond Y or N yet… Then compute a few of the time differences.  In my case, I got 1.63 seconds. 

NOTE: the times are in hours:minutes:seconds where seconds are resolved down to centiseconds (1/100th of a second). Then multiply by 10 for the number of milliseconds (1000 milliseconds per second divided by 100 operations in the loop) that were performed in each ping.  In my case then, I get 1.63 seconds per loop or 16.3 msec. per PING. And, then divide the desired delay by this number.

So, to get 333 msec, we would need 333/16.3 = 20.42.  Rounded down to 20 will give us 20*16.3 = 326 msec.  That’s the best we can do; it’s about 2% shorter than we said we wanted.

By the way, if you’re tempted to run all the pings using one command with the –n parameter like this:

ping 10.109.199.199 –n 20 –w > nul

Open in new window


I found that this won’t work.  It seems if the “-w” parameter is blank then the “-n” parameter makes no difference.  It can also be blank or it can be not used at all (which would suggest that the default of 4000 would be used).  If the “-w” parameter is blank then it just doesn’t matter what you do with “-n”.
 
Implementing a Millisecond-Resolution Delay
The code one might use to test a Windows batch file to effect a delay would be:

@ECHO OFF
:DELAY
SET number_of_pings= 20
@echo Start %time%
for /L %%a In (0 1 %number_of_pings%) do (
ping -n 1 -w 1.1.1.1 > nul
)
@echo end %time%
GOTO :DELAY

Open in new window

Then one can stop execution with CTRL+C and inspect the total delay to confirm that the desired total delay is being achieved.

A shorter version can be inserted into the actual batch file in which to implement a single delay:
 

REM On this machine the delay per ping is 16.3msec.
REM 333/16.3~20 pings
SET number_of_pings= 20
for /L %%a In (0 1 %number_of_pings%) do (
ping -n 1 -w 10.109.199.199 > nul
)

Open in new window

A Sample Application - A PING Probe

I developed this delay code segment to adjust ping intervals in a "ping probe" that I use to check continuity of communications both intra-network and into the internet world.  Here's the code for a probe using the delay.  So you will see two uses of PING; the first one is the delay and the second one is an actual PING.
 
@ECHO OFF
:VARIABLES
SET drive_letter=%1
IF "%1"=="" (SET drive_letter=c:)
echo Drive letter = %drive_letter%
REM ***************************SETUP***********************
SET Machine=%2
REM Edit the next line:
IF "%2"=="" (SET Machine=207.108.182.1)
echo Machine = %Machine%
echo.
REM Edit the next 5 lines according to the needs:
SET testname=QWEST
SET /a faillimit=2
SET pinginterval=500
SET pingtimeout=100
SET single_ping_delay=16.3
REM ***************No changes below*****
SET /a pings=%pinginterval%/%single_ping_delay%
@Echo pings = %pings%
SET fileloc=%drive_letter%\Users\public\probes\ping
SET pinglog=%fileloc%\%testname%_pinglog.txt
SET tracelog=%fileloc%\%testname%_tracelog.txt
SET pingtemp=%fileloc%\%testname%_pingtemp.txt
SET temptxt=%fileloc%\%testname%_temptxt.txt
REM **************************END SETUP********************
echo.
cd \
%drive_letter%
cd \
md users
cd users
md public
cd public
md probes
cd probes
md ping
cd ping
echo.

REM initialize counts and limits
SET /a pingcount=0
REM Zeros the contiguous ping failure count
SET /a failcount=0
ECHO %DATE%
ECHO %TIME%
REM Initializing TRACE then return to :PING
goto :TRACE

:PING
REM echo %time%
REM Delay between pings using ping -w [blank]

for /L %%a In (0 1 %pings%) do (
ping -n 1 -w 10.109.199.199 > nul
)

REM @ECHO add ping output to %pingtemp%.  This is NOT a delay!

ping -w %pingtimeout% -n 1 %Machine% >%pingtemp%

REM @ECHO Find "reply" and reset fail counter
(find /I "reply"   %pingtemp%>%pinglog%) && (set /a failcount=0 & goto :PING)

REM @ECHO Finding "request timed out" and increment fail counter
(find /I "request" %pingtemp%>%pinglog%) && set /a failcount=%failcount%+1

REM @ECHO Finding "unreachable" and increment fail counter
(find /I "unreachable" %pingtemp%>%pinglog%) && set /a failcount=%failcount%+1

REM @ECHO Check failcount
if %failcount% geq 1 echo failcount %failcount% Pings have failed  %date% %time%
if %failcount% geq 2 echo failcount %failcount% Pings have failed  %date% %time%>>%tracelog%
if %failcount% geq %faillimit% goto :TRACE
goto :PING

:TRACE

REM @ECHO Reset failcount to zero
set /a failcount=0

ECHO.
ECHO Trace Started
ECHO %DATE%
ECHO %TIME%
@ECHO.
@ECHO.>>%tracelog%
@ECHO Trace Started>>%tracelog%
@ECHO %DATE%>>%tracelog%
@ECHO %TIME%>>%tracelog%
@ECHO.>>%tracelog%
TRACERT -d -h 30 %machine% >>%tracelog%
@ECHO.>>%tracelog%
@ECHO Trace ended >>%tracelog%
@ECHO %DATE% >>%tracelog
@ECHO %TIME% >>%tracelog
@ECHO Trace ended
@ECHO %DATE%
@ECHO %TIME%

GOTO PING
:EOF

REM Program will loop until CTRL+C is pressed or window is closed.

end

Open in new window


Other than itself, this .bat file creates all the other files that are needed. It uses the directory:

C:\Users\Public\probes\ping
If PINGs are missed faillimit times in succession, a traceroute is run and recorded and the pinging continues. The command line window displays the total count of missed successive pings each time there's a missed ping. So, it's typical for it to show lines like this:
 
failcount 1 Pings have failed  Sun 02/08/2015 14:26:26.17
failcount 1 Pings have failed  Sun 02/08/2015 14:29:06.60
failcount 1 Pings have failed  Sun 02/08/2015 14:29:46.09

.

And, if there's a sequence of 3 missed pings in succession, and if faillimit=3, you would see: 

failcount 1 Pings have failed  Sun 02/08/2015 14:26:26.17
failcount 2 Pings have failed  Sun 02/08/2015 14:29:06.60
failcount 3 Pings have failed  Sun 02/08/2015 14:29:46.09
Trace Started
Sun 02/08/2015
14:29:14.66

Trace ended
Sun 02/08/2015
14:29:37.30
Then, in the tracelog file you may be able to see where the communication path had failed.
1
Comment
  • 3
  • 3
6 Comments
LVL 13

Expert Comment

by:louisfr
Of course the delay is short if you don't specify a value after -w since all the command does in that case is display an error message. That's also why the -n option does nothing.
0
LVL 27

Author Comment

by:Fred Marshall
louisfr:  You provide a reasonable explanation for why the -n option does nothing in the case mentioned.   It makes sense to me.  Nonetheless, it was only an observation from empirical tests and has no effect on the approach presented here.
0
LVL 13

Expert Comment

by:louisfr
The difference is that it's not an "undocumented feature" and it's not "worth documenting".
It's the normal behavior of any command: if there's an error in the parameters, display an error message and do nothing else.

It has a huge effect on the approach. You thought you found a way to reduce the timeout of ping and didn't go beyond that. Did you try removing the redirection to nul to see what actually is going on? Did you try using another command instead of ping? I'm guessing echo would get you shorter intervals.
0
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

LVL 27

Author Comment

by:Fred Marshall
Something here is worth documenting and I'd rather not argue about what that is.  It's not a research project.

Indeed, you've come up with some good suggestions as a result.
0
LVL 13

Expert Comment

by:louisfr
I'm sorry for the way I wrote my last reply. I think I can write understandable sentences in English, but I'm really not good at conveying the right feeling.
0
LVL 27

Author Comment

by:Fred Marshall
I'll try out those ideas you mentioned.  Thanks!
0

Featured Post

Bootstrap 4: Exploring New Features

Learn how to use and navigate the new features included in Bootstrap 4, the most popular HTML, CSS, and JavaScript framework for developing responsive, mobile-first websites.

Join & Write a Comment

Suggested Articles

With the power of JIRA, there's an unlimited number of ways you can customize it, use it and benefit from it. With that in mind, there's bound to be things that I wasn't able to cover in this course. With this summary we'll look at some places to go…
Simple Linear Regression

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month