vbScript - Run an External Program and Capture the Output
Please see my post vbScript - The Basics for more details on vbScript.
When you want to execute an external program for a particular result (such as resizing an image, as shown in a previous snippet) you can simply use the Run
method of the Wscript.Shell
object. However, if you want something a little more complex there is the Exec
method of the same object. This method gives you access to the standard input, output, and error streams. As such, you can take advantage, for example, of the increased flexibility of all of the built in commands available in a command shell.
Let's say you want to generate a list of all of the files of a particular type in a given folder, and all subfolders. To do that using the Scripting.FileSystemObject you would have to write a recursive routine that would enumerate all of the files in the given folder of that type, then call itself for each subfolder in the given folder. While not that complex it is still not trivial. It would be far easier to just be able to do
dir /s .b somefolder\*.jpg
and capture the resulting output. As it turns out this is easily done by
set wso = CreateObject("Wscript.Shell")
set exe = wso.Exec("cmd /c dir /s /b d:\temp\*.jpg")
That's it. Except for getting the output. For that you read the text from the standard output stream. You can read it line by line in a loop like
Do Until exe.StdOut.AtEndOfStream
Wscript.Echo exe.StdOut.ReadLine
Loop
I find it more convenient to real all of the output at once like
set wso = CreateObject("Wscript.Shell")
set exe = wso.Exec("cmd /c dir /s /b d:\temp\*.jpg")
sout = exe.StdOut.ReadAll
Most StdOut text will have lines terminated by vbCrLf, however, some programs ported from Unix/Linux, or output resulting from an operation of an odd text file, may return lines delimited only by vbLf. The following code will split output in either format into an array of lines.
sout = Replace(sout,vbCr,"")
If Len(sout) > 0 Then sout = Split(sout,vbLf): Else: sout = Split(""): End If
The Split("")
hand,es the case when StdOut returns no text. This allows the calling routine to handle both cases with a For Each
loop.
At the end of the listing you will see a block that looks like
''Test code '
If StrComp(Wscript.ScriptName,"execcmd.vbs",vbTextCompare) = 0 Then
For Each line In ExecCmd("cmd /c dir")
WScript.Echo line
Next
End If
This is something I borrowed from Python. Wscript.ScriptName
returns the unqualified (no path) name of the currently executing script. If you execute the file ExecCmd.vbs
by itself then the test code will run. As long as you ensure that any file you Include
this code into has a different name then the test code will not be executed. Feel free to just delete it or comment it out.
One final note. When executing dos shell commands (cmd) you should always specify /c
as an option. This will terminate the shell on completion. If you don't do this you may end up with orphan cmd.exe processes littering up memory.