PING w/ TIMESTAMP & - cmd

Using the standard windows CMD Prompt, I want to PING an IP "x" amount of times, and get results that are time stamped. The following does the job but it does not give PING STATISTICS at the end AND leave me ready for the next cmd.
ping -n 13 37.48.68.15|cmd /q /v /c "(pause&pause)>nul & for /l %a in () do (set /p "data=" && echo(!date! !time! !data!)&ping -n 2 37.48.68.15>nul"
I believe I am asking for 13 pings, but I only get 11, is there a resolve for that? AND Bonus Points if it will automatically print to a text file!
Photochop-EXAMPLE; http://www.plumbers.cc/images/tanki/cmd-example.jpg

Related

Keeping `for /f` redirect the output / getting the `do ()` to happen during command

Okay, so I'm trying to automate an ARM based CPU stress test program (it runs through the command prompt, and requires quite a bit of user input). What I'd like to do, is use for /f to watch the output, and run a few different sendkeys scripts when it see's their respective prompt strings. I've tried making two very barebones batch files to test this out:
The first is a simple batch file that asks for 3 separate inputs
#echo off
REM This is a file that asks for inputs
set /p q1="Please press 1: "
echo.
set /p q2="Please press 2: "
echo.
set /p q3="Please press 3: "
echo.
echo All buttons have been pressed,
echo.
echo button 1 was: %q1%
echo button 2 was: %q2%
echo button 3 was: %q3%
echo.
set /p foo="Press Enter to finish..."
The second is a batch file that runs the first (^) and looks for "Please Press 1: " in the output
#echo off
echo We will now launch the input command
echo.
timeout .5
echo in 5...
timeout 1
echo 4...
timeout 1
echo 3...
timeout 1
echo 2...
timeout 1
echo 1...
timeout 1
echo Launching...
for /f "delims= " %%i in ('Input.bat ^| find /i "Please press 1:"') do (
echo we did it
)
echo Did you make the right decisions?
set /p foo=
What I get as a result of this is a blank command prompt right after the "Launching..." Echo. If I press Enter four times, it comes back with the "we did it" echo along with the "Did you make the right decisions?" echo. So, finally on to the meat of my question. Is there any way to keep for /f from redirecting the stdout, as well as, is there any way to get for /f () do () to happen while the command is running?
So based on your request, sounds like you're trying to read strings from your batch1 script from a new batch2 script. To do this you will have to export your variables to a text document. From there, we can read the text document and gather the variables. If I am completely wrong on your request (It's a little hard to understand your request) then my oligopolies, hope those few tips can help you out at least.
To export files you need to use >>
For example: Echo This will be line one! >> Yourfile.txt
As another note, when you are done with the script, use goto :eof to exit.
Here is your 1st batch file:
#ECHO OFF
#DEL /Q %~dp0\strings.txt
REM This batch file asks for inputs
set /p q1="Please press 1: "
echo %q1% >> strings.txt
echo.
set /p q2="Please press 2: "
echo %q2% >> strings.txt
echo.
set /p q3="Please press 3: "
echo %q3% >> strings.txt
echo.
echo All buttons have been pressed,
echo.
echo button 1 was: %q1%
echo button 2 was: %q2%
echo button 3 was: %q3%
echo.
set /p foo="Press Enter to finish..."
goto :eof
Here is your 2nd batch file:
#ECHO OFF
echo We will now launch the input command.
echo.
echo in 5...
PING localhost -n 2 >nul
echo 4...
PING localhost -n 2 >nul
echo 3...
PING localhost -n 2 >nul
echo 2...
PING localhost -n 2 >nul
echo 1...
PING localhost -n 2 >nul
CLS
echo Launching...
:: Do action for each string. Use %%G to call the variable.
for /f "delims== tokens=*" %%G in (strings.txt) do (
echo Working on string: %%G
)
echo Did you make the right decisions?
pause > nul
DEL /Q %~dp0\strings.txt
goto :eof
Please keep in mind that instead of using timeout 1 you can actually use PING localhost -n 2 >nul so it does not actually freeze the prompt it's self.

Computer script for auto-reboot on network loss

I am working with a IP Camera network and need a script to run on each individual PC that will perform an auto-reboot when network loss happens. I would like to be able to have the PC ping the servers IP every 5 minutes and upon loss of connectivity the PC will reboot. Each PC has a Camera viewer but periodically looses network connection with the NVR. I found almost the same issue/solution here: http://www.cam-it.org/index.php?topic=2786.0
However the script provided didn't work for me. Below is the script I found and tried but didn't function the way I needed.
#Echo off
REM Put REM in front of Echo off to view the file output
REM ---------------------------------------------------------
REM WATCHDOG.CMD
REM Restarts PC after 3 unsuccessful attempts to PING the
REM POE switch
REM --------------------------------------------------------
SET COUNT=C:\Temp\WATCHDOG.txt
SET POESWITCH=192.168.1.253
SET ERRFLG=0
IF EXIST "%COUNT%" (
SET /P ERRFLG= <%COUNT%
)
IF %ERRFLG% GTR 2 (
Echo Restarting PC in 60 seconds. Run SHUTDOWN -a to abort.
DEL %COUNT%
SHUTDOWN -r -t 60 -f
GOTO :EOF
)
PING -n 1 %POESWITCH%|findstr /I /C:"timed out" /C:"unreachable" /C:"general failure"
if %ERRORLEVEL% == 1 Goto Done
SET /a ERRFLG +=1
ECHO %ERRFLG% > %COUNT%
:Done
(http://www.cam-it.org/index.php?topic=2786.0)
Any suggestions would be greatly appreciated.
Thanks,
Jordan
Add the reboot command and it should work for you to test a URL/IP address every 300 seconds
#echo off
set ip=www.google.com
:loop
ping -n 2 %ip% |find "TTL=" >nul || echo reboot command here
ping -n 300 localhost >nul
goto :loop

Batch ERRORLEVEL ping response

I'm trying to use a batch file to confirm a network connection using ping. I want to do batch run and then print if the ping was successful or not. The problem is that it always displays 'failure' when run as a batch. Here is the code:
#echo off
cls
ping racer | find "Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),"
if not errorlevel 1 set error=success
if errorlevel 1 set error=failure
cls
echo Result: %error%
pause
'racer' is the name of my computer. I'm having my computer ping itself so I can eliminate the variable of a poor connection. As I said before, the batch always results in failure. Oddly enough, the program works fine if I copy the code into the command prompt. Does anyone know why the program works fine in the command prompt but doesn't work as a batch?
Thanks
A more reliable ping error checking method:
#echo off
set "host=192.168.1.1"
ping -n 1 "%host%" | findstr /r /c:"[0-9] *ms"
if %errorlevel% == 0 (
echo Success.
) else (
echo FAILURE.
)
This works by checking whether a string such as 69 ms or 314ms is printed by ping.
(Translated versions of Windows may print 42 ms (with the space), hence we check for that.)
Reason:
Other proposals, such as matching time= or TTL are not as reliable, because pinging IPv6 addresses doesn't show TTL (at least not on my Windows 7 machine) and translated versions of Windows may show a translated version of the string time=. Also, not only may time= be translated, but sometimes it may be time< rather than time=, as in the case of time<1ms.
If you were to
echo "Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),"
you would see the % is stripped. You need to escape it as % has a special meaning within a batch file:
"Packets: Sent = 4, Received = 4, Lost = 0 (0%% loss),"
However its simpler to use TTL as the indication of success;
.. | find "TTL"
Testing for 0% loss may give a false positive, in this scenario:
Let's say you normally have a network drive on some_IP-address, and you want to find out whether or not it's on.
If that drive is off, and you ping some_IP-address, the IP address from which you ping, will respond:
Answer from your_own_IP-address: target host not reachable
... 0% loss
You might be better off using if exist or if not exist on that network location.
I 'm not exactly sure what the interaction between FIND and setting the error level is, but you can do this quite easily:
#echo off
for /f %%i in ('ping racer ^| find /c "(0%% loss)"') do SET MATCHES=%%i
echo %MATCHES%
This prints 0 if the ping failed, 1 if it succeeded. I made it look for just "0% loss" (not specifically 4 pings) so that the number of pings can be customized.
The percent sign has been doubled so that it's not mistaken for a variable that should be substituted.
The FOR trick serves simply to set the output of a command as the value of an environment variable.
Another variation without using any variable
ping racer -n 1 -w 100>nul || goto :pingerror
...
:pingerror
echo Host down
goto eof
:eof
exit /b
Yes ping fails to return the correct errorlevel. To check the network connection and the computer I used "net view computername" then checked %errorlevel% - simple and easy
First of all
>#echo off
>for /f %%i in ('ping racer ^| find /c "(0%% loss)"') do SET MATCHES=%%i
>echo %MATCHES%
Does not work. If it won't fail, it will detect 0%, because it has 0%.
If it fails, does not work either, because it will have 100% loss, which means, it found the 0% loss part behind the 10
10(0% loss)
Have it detect for 100% loss like so:
>for /f %%i in ('ping -n 1 -l 1 %pc% ^| find /c "(100%% loss)"') do SET check=%%i
Errorlevel might be a bit messed up, but it works like a charm:
>if '%check%'=='1' goto fail
>if '%check%'=='0' echo %pc% is online.&goto starting
1 means it failed
0 means it succeeded
In my script is use links.
Goto fail will go to :fail in my script which will message me that %pc% (which I'll have the user input in the beginning) is offline and will go for another run.
>:fail
>color 0c
>title %pc% is offline
>echo %pc% is offline
>PING -n 6 127.0.0.1>nul
>goto choice
I hope this helps.
The most simple solution to this I can think of:
set error=failure
ping racer -n 1 -w 100>nul 2>&1 && set error=success
Of course, -w needs to be adjusted if on a slow link (100ms might be too short over Dialup ;-))
regards
ping has an errorlevel output value. Success is 0, failure is 1.
Just do this:
C:\>ping 4.2.2.2
Pinging 4.2.2.2 with 32 bytes of data:
Reply from 4.2.2.2: bytes=32 time=28ms TTL=57
Reply from 4.2.2.2: bytes=32 time=29ms TTL=57
Reply from 4.2.2.2: bytes=32 time=30ms TTL=57
Reply from 4.2.2.2: bytes=32 time=29ms TTL=57
Ping statistics for 4.2.2.2:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 28ms, Maximum = 30ms, Average = 29ms
C:\>echo %errorlevel%
0
C:\>ping foo.bar
Ping request could not find host foo.bar. Please check the name and try again.
C:\>echo %errorlevel%
1
As you can see there is no need for all this scripting overkill.
Based on Alex K's note, this works for me on Windows 7:
#echo off
setlocal enableextensions enabledelayedexpansion
for /f %%i in (PCS.TXT) do (
SET bHOSTUP=0
ping -n 2 %%i |find "TTL=" > NUL && SET bHOSTUP=1
IF !bHOSTUP! equ 1 (
CALL :HOSTUP %%i
) else (
CALL :HOSTDOWN %%i
)
)
GOTO EOF
:HOSTUP
echo Host UP %1
GOTO EOF
:HOSTDOWN
echo Host DOWN %1
GOTO EOF
:EOF
exit /B
ping 198.168.57.98 && echo Success || echo failed
I liked the concept of the FIND in the ping results but why not just FIND the Reply from the Address being pinged?
In the example below I enter an IP address as a variable, PING that IP, then look for that variable in the reply string, using the FIND Command.
If the Reply String contains anything other than the correct IP it reports failure.
If you want you can just read the value of ERRORLEVEL from the FIND.
That will give you a reliable value to work with.
#echo off
Set /P IPAdd=Enter Address:
cls
ping %IPAdd% | find "Reply from %IPAdd%:"
if not errorlevel 1 set error=success
if errorlevel 1 set error=failure
cls
echo Result: %error%
pause
I needed to reset a wifi connection because it has issues. This was my quick solution.
#echo off
Rem Microsoft Windows 10 ping test to gateway.
Rem Run batch file from an administrative command prompt.
cls
:starting
Rem Send one ping to the gateway. Write the results to a file.
ping 192.168.1.1 -n 1 > pingtest.txt
Rem Search for unreachable in the file.
c:\windows\system32\findstr.exe "unreachable" pingtest.txt
Rem errorlevel 0 reset the adapter if 1 then wait 10 minutes and test again
if %errorlevel%==1 goto waiting
Rem unreachable was found reset the adapter.
Rem write the date and time the reset was done.
echo Reset date: %date% time: %time% >> resettimes.txt
Rem issue netsh interface show interface to find your adapter's name to reset
Rem my adapter is "wi-fi"
netsh interface set interface "wi-fi" disable
timeout /t 5
netsh interface set interface "wi-fi" enable
:waiting
echo "It is online waiting 10 minutes"
timeout /t 600
goto starting

Script to start traceroute if continuous ping fails, output to log

I want to continuously ping my home public IP address, and if the ping fails automatically do a traceroute to see where it's failing.
I've been trying to follow the comments made here:
http://social.technet.microsoft.com/Forums/en-US/ITCG/thread/efc97c66-60a6-4fd7-8be4-4b454d040ce5
Windows compatible would be preferable, bat or vbs would be best.
From anywhere on the internet I will lose my connection to my home network. From work I have started a ping and when it drops I've done a traceroute and it fails before it gets to my IP.
I need a log file to prove that it is not my modem, or router, or computer.
#echo off
set Address=google.com
:Loop
PING -n 5 127.0.0.1>nul
echo Pinging %Address%
%SystemRoot%\system32\ping.exe -n 1 %Address% | %SystemRoot%\system32\find.exe "TTL=" > NUL >> C:\pingtest\logfile.log
if %ERRORLEVEL% EQU 0 goto :Loop
echo Trace route %Address% at %date% %time% >> C:\pingtest\logfile.log
tracert %Address% >> C:\pingtest\logfile.log
goto Loop
This is what I ended up going with, if anyone else ever needs this. Essentially the "Ping -n 127.0.0.1>Nul" is to add a 5 second counter so that it only pinged the destination every 5 seconds, 5 can be changed to whatever value is needed.
Windows 7 has this problem where a ping may result with something like "reply from 192.168.1.5: Destination host unreachable". So instead of erroring out it gets a reply from itself and not the error level 1.
Instead of looking for Error Level 1 I choose to look for no result for TTL with "%SystemRoot%\system32\ping.exe -n 1 %Address% | %SystemRoot%\system32\find.exe "TTL=" > NUL"
Anyway, I'm sure the other answers here were very similar and may have worked, so I am ranking them up, but marking this as the answer.
Thanks all!
#echo off
set Address=www.google.com
set LogDir=C:\pingtest
md %LogDir%
%SystemRoot%\explorer.exe "%LogDir%"
echo PingTest script to monitor network connection. Control-C to exit.
echo Tests connection by pinging %Address%. Logs to %LogDir%\logfile.log.
echo %date% %time% Initial tracert (trace route) to %Address% >> %LogDir%\logfile.log
tracert %Address% >> %LogDir%\logfile.log
:Loop
REM 5 second delay
PING -n 5 -w 1 127.0.0.1>nul
echo %date% %time% Pinging %Address%
echo %date% %time% Pinging %Address% >> %LogDir%\logfile.log
%SystemRoot%\system32\ping.exe -n 1 %Address% | %SystemRoot%\system32\find.exe "TTL=" > NUL
if %ERRORLEVEL% EQU 0 goto :Loop
echo %date% %time% PING ERROR - Tracing route to %Address%
echo %date% %time% PING ERROR - Tracing route to %Address% >> %LogDir%\logfile.log
tracert %Address% >> %LogDir%\logfile.log
goto Loop
You could make a simple batch file that tries a ping and if it fails does a tracert, eg:
setlocal
set host=www.bigpond.com
set logfile=nettest.log
echo %date% %time%>>%logfile%
ping %host%>>%logfile%
if ERRORLEVEL 1 tracert %host%>>%logfile
endlocal
There's plenty of scope for refinement here.
Then create a scheduled task that runs it every five minutes or whatever suits you.
Alternatively you could include a loop with a 'sleep' in it. There's a poor man's sleep at Sleeping in a batch file that uses:
choice /d y /t 5 > nul
:LOOP
FOR /F "usebackq tokens=1" %%F IN (`ping localhost -n 1 -w 1 ^| find "Request"`) DO (
IF "%%F"=="Request" (
tracert localhost
)
)>>log.txt
FOR /F "usebackq tokens=1-4 delims=:." %%G IN (`echo %time%`) DO IF %G%H GTR 1400 GOTO:EOF
GOTO LOOP
Basically, this states do ping, if it finds a line that has an instance of the word Request (which only appears if you can't ping the address) perform a tracert. The -n and -w switches in PING tell it to jump only once and timeout after 1 second of not getting a response. This is perfectly fine if you are pinging your localhost. The second FOR statement is to have a stopping point. Change the 1400 to a time you wish for the script to stop (in military time of course).
I have just been looking for the same thing to investigate why a VPN keeps dropping on a wired connection, used one of the batch file suggestions above which was great.
Also found a nice little Java App which packages it for you here
Internet Connectivity Monitor
Simple to use and does the job :-)

How do I measure execution time of a command on the Windows command line?

Is there a built-in way to measure execution time of a command on the Windows command line?
PowerShell has a cmdlet for this called Measure-Command. You'll have to ensure that PowerShell is available on the machine that runs it.
PS> Measure-Command { echo hi }
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 0
Ticks : 1318
TotalDays : 1.52546296296296E-09
TotalHours : 3.66111111111111E-08
TotalMinutes : 2.19666666666667E-06
TotalSeconds : 0.0001318
TotalMilliseconds : 0.1318
Measure-Command captures the command's output. You can redirect the output back to your console using Out-Default:
PS> Measure-Command { echo hi | Out-Default }
hi
Days : 0
...
As Makotoe commented, Measure-Command returns a TimeSpan object, so the measured time is printed as a bunch of fields. You can format the object into a timestamp string using ToString():
PS> (Measure-Command { echo hi | Out-Default }).ToString()
hi
00:00:00.0001318
If the command inside Measure-Command changes your console text color, use [Console]::ResetColor() to reset it back to normal.
If you want
To measure execution time down to the hundredth of a second in (hh:mm:ss.ff format)
To not have to download and install a resource pack
To look like a huge DOS nerd (who doesn't)
Try copying the following script into a new batch file (e.g. timecmd.bat):
#echo off
#setlocal
set start=%time%
:: Runs your command
cmd /c %*
set end=%time%
set options="tokens=1-4 delims=:.,"
for /f %options% %%a in ("%start%") do set start_h=%%a&set /a start_m=100%%b %% 100&set /a start_s=100%%c %% 100&set /a start_ms=100%%d %% 100
for /f %options% %%a in ("%end%") do set end_h=%%a&set /a end_m=100%%b %% 100&set /a end_s=100%%c %% 100&set /a end_ms=100%%d %% 100
set /a hours=%end_h%-%start_h%
set /a mins=%end_m%-%start_m%
set /a secs=%end_s%-%start_s%
set /a ms=%end_ms%-%start_ms%
if %ms% lss 0 set /a secs = %secs% - 1 & set /a ms = 100%ms%
if %secs% lss 0 set /a mins = %mins% - 1 & set /a secs = 60%secs%
if %mins% lss 0 set /a hours = %hours% - 1 & set /a mins = 60%mins%
if %hours% lss 0 set /a hours = 24%hours%
if 1%ms% lss 100 set ms=0%ms%
:: Mission accomplished
set /a totalsecs = %hours%*3600 + %mins%*60 + %secs%
echo command took %hours%:%mins%:%secs%.%ms% (%totalsecs%.%ms%s total)
Usage
If you put timecmd.bat in a directory in your path, you can call it from anywhere like this:
timecmd [your command]
E.g.
C:\>timecmd pause
Press any key to continue . . .
command took 0:0:1.18
If you want to do output redirection, you can quote the command like this:
timecmd "dir c:\windows /s > nul"
This should handle commands that run from before- to after-midnight, but the output will be wrong if your command runs for 24 hours or more.
Hehe, the most simple solution might be this:
echo %time%
YourApp.exe
echo %time%
This works on every Windows out of the box.
In case of an application using console output, it might be convenient to store the starting time in a temporary variable:
set startTime=%time%
YourApp.exe
echo Start Time: %startTime%
echo Finish Time: %time%
Just a little expansion of the answer from Casey.K about using the Measure-Command from PowerShell:
You can invoke PowerShell from the standard command prompt, like this:
powershell -Command "Measure-Command {echo hi}"
This will eat the standard output, but you can prevent that by adding | Out-Default like this from PowerShell:
Measure-Command {echo hi | Out-Default}
Or from a command prompt:
powershell -Command "Measure-Command {echo hi | Out-Default}"
Of course, you're free to wrap this in a script file *.ps1 or *.bat.
If you are using Windows 2003 (note that windows server 2008 and later are not supported) you can use The Windows Server 2003 Resource Kit, which contains timeit.exe that displays detailed execution stats. Here is an example, timing the command "timeit -?":
C:\>timeit timeit -?
Invalid switch -?
Usage: TIMEIT [-f filename] [-a] [-c] [-i] [-d] [-s] [-t] [-k keyname | -r keyname] [-m mask] [commandline...]
where: -f specifies the name of the database file where TIMEIT
keeps a history of previous timings. Default is .\timeit.dat
-k specifies the keyname to use for this timing run
-r specifies the keyname to remove from the database. If
keyname is followed by a comma and a number then it will
remove the slowest (positive number) or fastest (negative)
times for that keyname.
-a specifies that timeit should display average of all timings
for the specified key.
-i specifies to ignore non-zero return codes from program
-d specifies to show detail for average
-s specifies to suppress system wide counters
-t specifies to tabular output
-c specifies to force a resort of the data base
-m specifies the processor affinity mask
Version Number: Windows NT 5.2 (Build 3790)
Exit Time: 7:38 am, Wednesday, April 15 2009
Elapsed Time: 0:00:00.000
Process Time: 0:00:00.015
System Calls: 731
Context Switches: 299
Page Faults: 515
Bytes Read: 0
Bytes Written: 0
Bytes Other: 298
You can get TimeIt in the Windows 2003 Resource Kit. It's not available for direct download from the Microsoft Download Center, but one can still get it from the archive.org - Windows Server 2003 Resource Kit Tools.
The one-liner I use in Windows Server 2008 R2 is:
cmd /v:on /c "echo !TIME! & *mycommand* & echo !TIME!"
So long as mycommand doesn't require quotes (which screws with cmd's quote processing). The /v:on is to allow for the two different TIME values to be evaluated independently rather than once at the execution of the command.
If you have a command window open and call the commands manually, you can display a timestamp on each prompt, e.g.
prompt $d $t $_$P$G
It gives you something like:
23.03.2009 15:45:50,77
C:\>
If you have a small batch script that executes your commands, have an empty line before each command, e.g.
(empty line)
myCommand.exe
(next empty line)
myCommand2.exe
You can calculate the execution time for each command by the time information in the prompt. The best would probably be to pipe the output to a textfile for further analysis:
MyBatchFile.bat > output.txt
Since others are recommending installing things like freeware and PowerShell, you could also install Cygwin, which would give you access to many basic Unix commands like time:
abe#abe-PC:~$ time sleep 5
real 0m5.012s
user 0m0.000s
sys 0m0.000s
Not sure how much overhead Cygwin adds.
Not quite as elegant as some of the functionality on Unix, but create a cmd file which looks like:
#echo off
time < nul
yourexecutable.exe > c:\temp\output.txt
time < nul
rem on newer windows system you can try time /T
That will display the start and stop times like so:
The current time is: 10:31:57.92
Enter the new time:
The current time is: 10:32:05.94
Enter the new time:
I use freeware called "GS Timer".
Just make a batch file like this:
timer
yourapp.exe
timer /s
If you need a set of times, just pipe the output of timer /s into a .txt file.
You can get it here: Gammadyne's Free DOS Utilities
The resolution is 0.1 seconds.
I'm using Windows XP and for some reason timeit.exe does not work for me. I found another alternative - PTIME. This works very well.
http://www.pc-tools.net/win32/ptime/
Example -
C:\> ptime
ptime 1.0 for Win32, Freeware - http://www.pc-tools.net/
Copyright(C) 2002, Jem Berkes <jberkes#pc-tools.net>
Syntax: ptime command [arguments ...]
ptime will run the specified command and measure the execution time
(run time) in seconds, accurate to 5 millisecond or better. It is an
automatic process timer, or program timer.
C:\> ptime cd
ptime 1.0 for Win32, Freeware - http://www.pc-tools.net/
Copyright(C) 2002, Jem Berkes <jberkes#pc-tools.net>
=== cd ===
C:\
Execution time: 0.015 s
As long as it doesn't last longer than 24hours...
#echo off
set starttime=%TIME%
set startcsec=%STARTTIME:~9,2%
set startsecs=%STARTTIME:~6,2%
set startmins=%STARTTIME:~3,2%
set starthour=%STARTTIME:~0,2%
set /a starttime=(%starthour%*60*60*100)+(%startmins%*60*100)+(%startsecs%*100)+(%startcsec%)
:TimeThis
ping localhost
set endtime=%time%
set endcsec=%endTIME:~9,2%
set endsecs=%endTIME:~6,2%
set endmins=%endTIME:~3,2%
set endhour=%endTIME:~0,2%
if %endhour% LSS %starthour% set /a endhour+=24
set /a endtime=(%endhour%*60*60*100)+(%endmins%*60*100)+(%endsecs%*100)+(%endcsec%)
set /a timetaken= ( %endtime% - %starttime% )
set /a timetakens= %timetaken% / 100
set timetaken=%timetakens%.%timetaken:~-2%
echo.
echo Took: %timetaken% sec.
There's also TimeMem (March 2012):
This is a Windows utility which executes a program and displays its
execution time, memory usage, and IO statistics. It is similar in
functionality to the Unix time utility.
Here is a
Postfix timer version:
Usage example:
timeout 1 | TimeIt.cmd
Execution took ~969 milliseconds.
Copy & paste this into some editor like for example Notepad++ and save it as TimeIt.cmd:
:: --- TimeIt.cmd ----
#echo off
setlocal enabledelayedexpansion
call :ShowHelp
:: Set pipeline initialization time
set t1=%time%
:: Wait for stdin
more
:: Set time at which stdin was ready
set t2=!time!
:: Calculate difference
Call :GetMSeconds Tms1 t1
Call :GetMSeconds Tms2 t2
set /a deltaMSecs=%Tms2%-%Tms1%
echo Execution took ~ %deltaMSecs% milliseconds.
endlocal
goto :eof
:GetMSeconds
Call :Parse TimeAsArgs %2
Call :CalcMSeconds %1 %TimeAsArgs%
goto :eof
:CalcMSeconds
set /a %1= (%2 * 3600*1000) + (%3 * 60*1000) + (%4 * 1000) + (%5)
goto :eof
:Parse
:: Mask time like " 0:23:29,12"
set %1=!%2: 0=0!
:: Replace time separators with " "
set %1=!%1::= !
set %1=!%1:.= !
set %1=!%1:,= !
:: Delete leading zero - so it'll not parsed as octal later
set %1=!%1: 0= !
goto :eof
:ShowHelp
echo %~n0 V1.0 [Dez 2015]
echo.
echo Usage: ^<Command^> ^| %~nx0
echo.
echo Wait for pipe getting ready... :)
echo (Press Ctrl+Z ^<Enter^> to Cancel)
goto :eof
^ - Based on 'Daniel Sparks' Version
Depending on the version of Windows you're using, just running bash will put you into Bash mode. This will allow you to use a bunch of commands that are not available on PowerShell directly (like the time command). Timing your command is now as easy as executing:
# The clause <your-command> (without the angle brackets) denotes the command you want to run.
$ time <your-command>
Note: You can easily quit from Bash mode and return back into your mainstream shell by running exit while in Bash mode.
This worked for me perfectly (Windows 10) after trying out other methods (like Measure-Command) which sometimes produce undesired stats. Hope this works for you as well.
An alternative to measure-time is simply "Get-Date". You don't have that hassle with forwarding output and so on.
$start = Get-Date
[System.Threading.Thread]::Sleep(1500)
$(Get-Date) - $start
Output:
Days : 0
Hours : 0
Minutes : 0
Seconds : 1
Milliseconds : 506
Ticks : 15060003
TotalDays : 1.74305590277778E-05
TotalHours : 0.000418333416666667
TotalMinutes : 0.025100005
TotalSeconds : 1.5060003
TotalMilliseconds : 1506.0003
This is a one-liner which avoids delayed expansion, which could disturb certain commands:
cmd /E /C "prompt $T$$ & echo.%TIME%$ & COMMAND_TO_MEASURE & for %Z in (.) do rem/ "
The output is something like:
14:30:27.58$
...
14:32:43.17$ rem/
For long-term tests replace $T by $D, $T and %TIME% by %DATE%, %TIME% to include the date.
To use this inside of a batch file, replace %Z by %%Z.
Update
Here is an improved one-liner (without delayed expansion too):
cmd /E /C "prompt $D, $T$$ & (for %# in (.) do rem/ ) & COMMAND_TO_MEASURE & for %# in (.) do prompt"
The output looks similar to this:
2015/09/01, 14:30:27.58$ rem/
...
2015/09/01, 14:32:43.17$ prompt
This approach does not include the process of instancing a new cmd in the result, nor does it include the prompt command(s).
In case anyone else has come here looking for an answer to this question, there's a Windows API function called GetProcessTimes(). It doesn't look like too much work to write a little C program that would start the command, make this call, and return the process times.
In the directory where your program is, type notepad mytimer.bat, click 'yes' to create a new file.
Paste the code below, replacing YourApp.exe with your program, then save.
#echo off
date /t
time /t
YourApp.exe
date /t
time /t
Type mytimer.bat in the command line then press Enter.
Here is my method, no conversion and no ms. It is useful to determine encoding durations (limited to 24 hours though):
#echo off
:start
REM Start time storage
set ST=%time%
echo Process started at %ST%
echo.
echo.
REM Your commands
REM Your commands
REM Your commands
:end
REM Start Time Definition
for /f "tokens=1-3 delims=:" %%a in ("%ST%") do set /a h1=%%a & set /a m1=%%b & set /a s1=%%c
REM End Time Definition
for /f "tokens=1-3 delims=:" %%a in ("%TIME%") do set /a h2=%%a & set /a m2=%%b & set /a s2=%%c
REM Difference
set /a h3=%h2%-%h1% & set /a m3=%m2%-%m1% & set /a s3=%s2%-%s1%
REM Time Adjustment
if %h3% LSS 0 set /a h3=%h3%+24
if %m3% LSS 0 set /a m3=%m3%+60 & set /a h3=%h3%-1
if %s3% LSS 0 set /a s3=%s3%+60 & set /a m3=%m3%-1
echo Start : %ST%
echo End : %time%
echo.
echo Total : %h3%:%m3%:%s3%
echo.
pause
my code gives you the running time in milliseconds, up to 24 hrs, it is locale insensitive, and accounts for negative values if code runs through midnight. it uses delayed expansion, and should be saved in a cmd/bat file.
before your code:
SETLOCAL EnableDelayedExpansion
for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set t=%%I
set /a t1 = %t:~8,1%*36000 + %t:~9,1%*3600 + %t:~10,1%*600 + %t:~11,1%*60 + %t:~12,1%*10 + %t:~13,1% && set t1=!t1!%t:~15,3%
after your code:
for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set t=%%I
set /a t2 = %t:~8,1%*36000 + %t:~9,1%*3600 + %t:~10,1%*600 + %t:~11,1%*60 + %t:~12,1%*10 + %t:~13,1% && set t2=!t2!%t:~15,3%
set /a t2-=t1 && if !t2! lss 0 set /a t2+=24*3600000
if you want running time in HH:mm:ss.000 format, add:
set /a "h=t2/3600000,t2%%=3600000,m=t2/60000,t2%%=60000" && set t2=00000!t2!&& set t2=!t2:~-5!
if %h% leq 9 (set h=0%h%) && if %m% leq 9 (set m=0%m%)
set t2=%h%:%m%:%t2:~0,2%.%t2:~2,3%
ENDLOCAL
variable t2 holds your running time, you can echo %t2% to display it.
This is a comment/edit to Luke Sampson's nice timecmd.bat and reply to
For some reason this only gives me output in whole seconds... which for me is useless. I mean that I run timecmd pause, and it always results in 1.00 sec, 2.00 sec, 4.00 sec... even 0.00 sec! Windows 7. – Camilo Martin Sep 25 '13 at 16:00 "
On some configurations the delimiters may differ. The following change should cover atleast most western countries.
set options="tokens=1-4 delims=:,." (added comma)
The %time% milliseconds work on my system after adding that ','
(*because site doesn't allow anon comment and doesn't keep good track of identity even though I always use same guest email which combined with ipv6 ip and browser fingerprint should be enough to uniquely identify without password)
Another approach with powershell:
#echo off
for /f %%t in ('powershell "(get-date).tofiletime()"') do set mst=%%t
rem some commands
powershell ((get-date).tofiletime() - %mst%)
this will print the execution time in milliseconds.
If you have CMake installed, you can just run following command.
cmake -E time <the_command_to_measure_run_time>
#echo off & setlocal
set start=%time%
REM Do stuff to be timed here.
REM Alternatively, uncomment the line below to be able to
REM pass in the command to be timed when running this script.
REM cmd /c %*
set end=%time%
REM Calculate time taken in seconds, to the hundredth of a second.
REM Assumes start time and end time will be on the same day.
set options="tokens=1-4 delims=:."
for /f %options% %%a in ("%start%") do (
set /a start_s="(100%%a %% 100)*3600 + (100%%b %% 100)*60 + (100%%c %% 100)"
set /a start_hs=100%%d %% 100
)
for /f %options% %%a in ("%end%") do (
set /a end_s="(100%%a %% 100)*3600 + (100%%b %% 100)*60 + (100%%c %% 100)"
set /a end_hs=100%%d %% 100
)
set /a s=%end_s%-%start_s%
set /a hs=%end_hs%-%start_hs%
if %hs% lss 0 (
set /a s=%s%-1
set /a hs=100%hs%
)
if 1%hs% lss 100 set hs=0%hs%
echo.
echo Time taken: %s%.%hs% secs
echo.
The following script uses only "cmd.exe" and outputs the number of milliseconds from the time a pipeline is created to the time that the process preceding the script exits. i.e., Type your command, and pipe the to the script. Example: "timeout 3 | runtime.cmd" should yield something like "2990." If you need both the runtime output and the stdin output, redirect stdin before the pipe - ex: "dir /s 1>temp.txt | runtime.cmd" would dump the output of the "dir" command to "temp.txt" and would print the runtime to the console.
:: --- runtime.cmd ----
#echo off
setlocal enabledelayedexpansion
:: find target for recursive calls
if not "%1"=="" (
shift /1
goto :%1
exit /b
)
:: set pipeline initialization time
set t1=%time%
:: wait for stdin
more > nul
:: set time at which stdin was ready
set t2=!time!
::parse t1
set t1=!t1::= !
set t1=!t1:.= !
set t1=!t1: 0= !
:: parse t2
set t2=!t2::= !
set t2=!t2:.= !
set t2=!t2: 0= !
:: calc difference
pushd %~dp0
for /f %%i in ('%0 calc !t1!') do for /f %%j in ('%0 calc !t2!') do (
set /a t=%%j-%%i
echo !t!
)
popd
exit /b
goto :eof
:calc
set /a t=(%1*(3600*1000))+(%2*(60*1000))+(%3*1000)+(%4)
echo !t!
goto :eof
endlocal
The answer of driblio can be made a little shorter (though not much readable)
#echo off
:: Calculate the start timestamp
set _time=%time%
set /a _hours=100%_time:~0,2%%%100,_min=100%_time:~3,2%%%100,_sec=100%_time:~6,2%%%100,_cs=%_time:~9,2%
set /a _started=_hours*60*60*100+_min*60*100+_sec*100+_cs
:: yourCommandHere
:: Calculate the difference in cSeconds
set _time=%time%
set /a _hours=100%_time:~0,2%%%100,_min=100%_time:~3,2%%%100,_sec=100%_time:~6,2%%%100,_cs=%_time:~9,2%
set /a _duration=_hours*60*60*100+_min*60*100+_sec*100+_cs-_started
:: Populate variables for rendering (100+ needed for padding)
set /a _hours=_duration/60/60/100,_min=100+_duration/60/100%%60,_sec=100+(_duration/100%%60%%60),_cs=100+_duration%%100
echo Done at: %_time% took : %_hours%:%_min:~-2%:%_sec:~-2%.%_cs:~-2%
::prints something like:
::Done at: 12:37:53,70 took: 0:02:03.55
To the remark of Luke Sampson this version is octal safe, though the task should be completed in 24 hours.
Having Perl installed the hires solution available, run:
C:\BATCH>time.pl "echo Fine result"
0.01063
Fine result
STDERR comes before measured seconds
#!/usr/bin/perl -w
use Time::HiRes qw();
my $T0 = [ Time::HiRes::gettimeofday ];
my $stdout = `#ARGV`;
my $time_elapsed = Time::HiRes::tv_interval( $T0 );
print $time_elapsed, "\n";
print $stdout;
A solution using pure PHP for cmd and one env. variable:
#echo off
setlocal enableextensions
REM set start time env var
FOR /F "tokens=* USEBACKQ" %%F IN (`php -r "echo microtime(true);"`) DO ( SET start_time=%%F )
## PUT_HERE_THE_COMMAND_TO_RUN ##
REM echo elapsed time
php -r "echo 'elapsed: ' . (round(microtime(true) - trim(getenv('start_time')), 2)) . ' seconds' . mb_convert_encoding('
', 'UTF-8', 'HTML-ENTITIES');"
no need for cygwin or non-trusted utilities. Usefull when PHP is locally available
precision and output format can be easily tweaked
the same idea can be ported for PowerShell
Using a sub to return time in hundredths of second
::tiemeit.cmd
#echo off
Setlocal EnableDelayedExpansion
call :clock
::call your_command or more > null to pipe this batch after your_command
call :clock
echo %timed%
pause
goto:eof
:clock
if not defined timed set timed=0
for /F "tokens=1-4 delims=:.," %%a in ("%time%") do (
set /A timed = "(((1%%a - 100) * 60 + (1%%b - 100)) * 60 + (1%%c - 100)) * 100 + (1%%d - 100)- %timed%"
)
goto:eof

Resources