How Can I Modify the Output of the Ping Command?
Hey, Scripting Guy! How can I place the current date and time at the beginning of each line of Ping.exe output?
Hey, AL. We have to admit, we were a little shocked by your question. Change the output of the Ping command? Really, AL. Would you ask us to rewrite Romeo and Juliet, giving it a more happy and upbeat ending? Would you ask us to fix up the Mona Lisa, giving Mona blonde hair and maybe a cute little butterfly tattoo? Would you ask us to take the peanuts out of peanut M&M’s and replace them with soybeans? Some things should not be tampered with; they’re perfectly fine just the way they are.
But, to tell you the truth, we don’t consider Ping.exe to be one of those things:
Set objShell = CreateObject(“WScript.Shell”)
Set objWshScriptExec = objShell.Exec(“ping 192.168.1.1″)
Set objStdOut = objWshScriptExec.StdOut
Do Until objStdOut.AtEndOfStream strLine = objStdOut.ReadLine If Len(strLine) > 2 Then WScript.Echo Now & ” — ” & strLine Else Wscript.Echo strLine End If Loop
So what are we doing here? Well, to begin with, we’re creating an instance of the Wscript.Shell object. After that, we call the Shell object’s Exec method, asking Exec to run the command-line command ping 192.168.1.1:
Set objWshScriptExec = objShell.Exec(“ping 192.168.1.1”)
If you aren’t familiar with the Exec method (which was introduced as part of Windows Script Host version 5.6) it’s actually a nifty little command. Exec is similar to the Run method; the primary difference is that while the Run method runs a command-line tool in a visible command window, the Exec method runs that same command-line tool in a hidden window. When you call Ping.exe using Exec, you’ll never see Ping – or its output – onscreen.
That’s a good point: Ping isn’t really all that useful if you never see the results, is it? But that’s OK: we can still get at the output. That’s because a command-line tool run using Exec has all its output stored in the StdOut property of the WSHScriptExec object (an object we created at the same time we called the Exec method). To get at the output of Ping.exe we simply need to read the value of the StdOut property.
So let’s see how we go about doing that. To begin with, here’s a line of code that binds us to the StdOut property:
Set objStdOut = objWshScriptExec.StdOut
After we’ve made the connection we set up a Do Until loop that reads StdOut line-by-line until there are no more lines to read (that is, until the AtEndOfStream property is true). Admittedly, we don’t need to read StdOut line-by-line; we’re only doing it in this case because we want to put the current date and time at the beginning of each line.
Note. Admittedly, we’re cheating a tiny bit: we’re actually calling Ping, waiting for the command to finish, and then – slightly after the fact – adding the date and time to the beginning of each line. That means our times will always be a few seconds off. However, that’s about the best we can do: we can’t ask Ping to issue the first ping, wait for us to grab the results and tack on the date and time, and only then run the second ping. If you feel the need to get that level of accuracy – and if you’re running Windows XP or Windows Server 2003 – then you might want to use the WMI class Win32_PingStatus and, in essence, create your own, customized version of Ping.exe.
Inside the loop we use this line of code to read the first line from StdOut:
strLine = objStdOut.ReadLine
We then use the Len function to determine whether or not the line has more than two characters in it. Why? Well, Ping’s output typically includes a few blank lines; because we don’t want to stick the current date and time on a blank line we use a little bit of programming intelligence to weed out blank lines. So then why do we check for lines greater than 2 characters? Shouldn’t we check for lines that have 0 characters?
That would seem to make sense. However, in command-line output a blank line doesn’t really have 0 characters; instead a blank line actually has two characters: a carriage return and a linefeed. If we checked for lines that had a length equal to 0 characters we’d never find one.
Suppose a line does have more than two characters in it. In that case we echo back the current date and time (using the VBScript function Now) followed by the line of code we read in from StdOut:
WScript.Echo Now & ” — ” & strLine
If the line doesn’t have more than two characters then it must be a blank line. In that case, we don’t attach the current date and time but instead echo back just the value read in from StdOut:
Will that do the trick? Judge for yourself:
8/6/2006 2:42:45 PM — Pinging 192.168.1.1 with 32 bytes of data:
8/6/2006 2:42:45 PM — Reply from 192.168.1.1: bytes=32 time<1ms TTL=128 8/6/2006 2:42:46 PM — Reply from 192.168.1.1: bytes=32 time<1ms TTL=128 8/6/2006 2:42:47 PM — Reply from 192.168.1.1: bytes=32 time<1ms TTL=128 8/6/2006 2:42:48 PM — Reply from 192.168.1.1: bytes=32 time<1ms TTL=128
8/6/2006 2:42:48 PM — Ping statistics for 192.168.1.1: 8/6/2006 2:42:48 PM — Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), 8/6/2006 2:42:48 PM — Approximate round trip times in milli-seconds: 8/6/2006 2:42:48 PM — Minimum = 0ms, Maximum = 0ms, Average = 0ms
Note. Incidentally, many years ago the legendary Dean Tsaltas wrote a Tales From the Script column that, among other things, used this same approach to show how you can modify the output you get back from command-line tools. If that sounds interesting to you check it out. (This, by the way, was the very first column published in the Script Center. And it remains as useful today as it was back in 2002!)
We hope that helps, AL. As for putting a butterfly tattoo on the Mona Lisa, though, well, we’re afraid we can’t help you there: