• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

StdOut.ReadAll blocking?

L

lucadentella

#1
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!
 

My Computer

O

Old Pedant

#2
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
 

My Computer

L

lucadentella

#3
Hello!

Thanks! Your solution resolved my problem!


> 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
 

My Computer

Users Who Are Viewing This Thread (Users: 1, Guests: 0)