Reputation: 113
My VBScript does not show the results of any command I execute. I know the command gets executed but I would like to capture the result.
I have tested many ways of doing this, for example the following:
Const WshFinished = 1
Const WshFailed = 2
strCommand = "ping.exe 127.0.0.1"
Set WshShell = CreateObject("WScript.Shell")
Set WshShellExec = WshShell.Exec(strCommand)
Select Case WshShellExec.Status
Case WshFinished
strOutput = WshShellExec.StdOut.ReadAll
Case WshFailed
strOutput = WshShellExec.StdErr.ReadAll
End Select
WScript.StdOut.Write strOutput 'write results to the command line
WScript.Echo strOutput 'write results to default output
But it does not print any results. How do I capture StdOut
and StdErr
?
Upvotes: 11
Views: 35016
Reputation: 59
You should read both streams INSIDE the loop as well as after it. When your process is verbose then it will block on the I/O buffer when this buffer will not be emptyfied succesively!!!
In practice I use this schema in many scripts. It collects both streams: the output (as Shell.Exec called apps can return output info) and error.
Dim vErrStr
vErrStr = ""
Dim vOutStr
vOutStr = ""
Do While oExec.Status = 0
WScript.Sleep 1000
If Not oExec.StdErr.AtEndOfStream Then
vErrStr = vErrStr & oExec.StdErr.ReadAll
End If
If Not oExec.StdOut.AtEndOfStream Then
vOutStr = vOutStr & oExec.StdOut.ReadAll
End If
Loop
vExitCode = oExec.ExitCode
If Not oExec.StdErr.AtEndOfStream Then
vErrStr = vErrStr & oExec.StdErr.ReadAll
End If
If Not oExec.StdOut.AtEndOfStream Then
vOutStr = vOutStr & oExec.StdOut.ReadAll
End If
Dim vEMStr
vEMStr = vErrStr & IIf((vErrStr <> "") And (vOutStr <> ""), " | ", "") & vOutStr
Upvotes: 3
Reputation: 559
I think Tomek's answer is good, but incomplete.
Here's a code example.
Private Sub ExecuteCommand(sCommand$)
Dim wsh As Object
Set wsh = CreateObject("WScript.Shell")
Dim oExec As Object, oOut As TextStream
'Exec the command
Set oExec = wsh.Exec(sCommand$)
Set oOut = oExec.StdOut
'Wait for the command to finish
While Not oOut.AtEndOfStream
Call Debug.Print(oOut.ReadLine)
Wend
Select Case oExec.Status
Case WshFinished
Case WshFailed
Err.Raise 1004, "EndesaSemanal.ExecuteCommand", "Error: " & oExec.StdErr.ReadAll()
End Select
End Sub
Upvotes: 1
Reputation: 53600
WScript.Shell.Exec()
returns immediately, even though the process it starts does not. If you try to read Status
or StdOut
right away, there won't be anything there.
The MSDN documentation suggests using the following loop:
Do While oExec.Status = 0
WScript.Sleep 100
Loop
This checks Status
every 100ms until it changes. Essentially, you have to wait until the process completes, then you can read the output.
With a few small changes to your code, it works fine:
Const WshRunning = 0
Const WshFinished = 1
Const WshFailed = 2
strCommand = "ping.exe 127.0.0.1"
Set WshShell = CreateObject("WScript.Shell")
Set WshShellExec = WshShell.Exec(strCommand)
Do While WshShellExec.Status = WshRunning
WScript.Sleep 100
Loop
Select Case WshShellExec.Status
Case WshFinished
strOutput = WshShellExec.StdOut.ReadAll()
Case WshFailed
strOutput = WshShellExec.StdErr.ReadAll()
End Select
WScript.StdOut.Write(strOutput) 'write results to the command line
WScript.Echo(strOutput) 'write results to default output
Upvotes: 17