Hello!

I'm working on a script using the WshShell.Exec() method.
To avoid buffer overflow problem (if I read the whole StdOut at the
end of the execution, sometimes my script hangs) I found a suggestion
on the "Hey, Scripting Guy!" MS blog: use a StdOut.ReadAll inside the
waiting loop.

But please notice these two examples:

-- Ex1, without ReadAll --

Dim elapsedSecs
elapsedSecs = 0

Dim quit
quit = False

Dim objShell
Set objShell = CreateObject("WScript.Shell")

Dim objCmd
Set objCmd = objShell.Exec("ping 10.113.203.200")

Do While quit = False

If objCmd.Status = 1 Then
quit = True
Else
WScript.Sleep 100
elapsedSecs = elapsedSecs + 0.1
End If


Loop

WScript.Echo "Elapsed seconds: " & elapsedSecs

-- output: "Elapsed seconds: 2,8"


-- Ex2, with ReadAll --

Dim elapsedSecs
elapsedSecs = 0

Dim quit
quit = False

Dim objShell
Set objShell = CreateObject("WScript.Shell")

Dim objCmd
Set objCmd = objShell.Exec("ping 10.113.203.200")

Do While quit = False

If Not objCmd.StdOut.AtEndOfStream Then
outBuffer = outBuffer & objCmd.StdOut.ReadAll
End If

If objCmd.Status = 1 Then
quit = True
Else
WScript.Sleep 100
elapsedSecs = elapsedSecs + 0.1
End If


Loop

WScript.Echo "Elapsed seconds: " & elapsedSecs

-- output: "Elapsed seconds: 0"


It seems ReadAll is blocking my loop until the objCmd exits... why?
thanks!

RE: StdOut.ReadAll blocking? by OldPedant

OldPedant
Fri Jul 11 15:17:00 CDT 2008

ReadAll does a *synchronous* read.

It really and truly means "read all output produced by writes to StdOut by
the given object."

So of course it has to wait until the logical EOF is received from the thing
it is reading from. And that doesn't happen with PING until the ping object
is done.

How about trying ReadLine???

startTime = Timer( )
quit = False
outBuffer = ""
Set objShell = CreateObject("WScript.Shell")
Set objCmd = objShell.Exec("ping 10.113.203.200")
Do
If Not objCmd.StdOut.AtEndOfStream Then
outBuffer = outBuffer & objCmd.StdOut.ReadLine
End If
If objCmd.Status = 1 Then Exit Do
If timer( ) > startTime + 20 Then
outBuffer = outBuffer & vbNewLine & "*** TIMED OUT ***"
Exit Do
End If
WScript.Sleep 100
Loop
endTime = Timer( )
WScript.Echo "Elapsed seconds: " & (endTime - startTime)
WScript.Echo outBuffer




Re: StdOut.ReadAll blocking? by lucadentella

lucadentella
Mon Jul 14 02:37:35 CDT 2008

Hello!

Thanks! Your solution resolved my problem!


> ReadAll does a *synchronous* read. =A0
>
> It really and truly means "read all output produced by writes to StdOut b=
y
> the given object."
>
> So of course it has to wait until the logical EOF is received from the th=
ing
> it is reading from. =A0And that doesn't happen with PING until the ping o=
bject
> is done.
>
> How about trying ReadLine???
>
> startTime =3D Timer( )
> quit =3D False
> outBuffer =3D ""
> Set objShell =3D CreateObject("WScript.Shell")
> Set objCmd =3D objShell.Exec("ping 10.113.203.200")
> Do
> =A0 =A0 If Not objCmd.StdOut.AtEndOfStream Then
> =A0 =A0 =A0 =A0 =A0outBuffer =3D outBuffer & objCmd.StdOut.ReadLine
> =A0 =A0 End If
> =A0 =A0 If objCmd.Status =3D 1 Then Exit Do
> =A0 =A0 If timer( ) > startTime + 20 Then
> =A0 =A0 =A0 =A0 =A0outBuffer =3D outBuffer & vbNewLine & "*** TIMED OUT *=
**"
> =A0 =A0 =A0 =A0 =A0Exit Do
> =A0 =A0 End If
> =A0 =A0 WScript.Sleep 100
> Loop
> endTime =3D Timer( )
> WScript.Echo "Elapsed seconds: " & (endTime - startTime)
> WScript.Echo outBuffer