Process control

bartj

New member
Joined
Mar 26, 2009
Messages
3
Programming Experience
5-10
Hello,

Am writing code using VB.net 2005 and am attempting to launch a 3rd party console application and capture stdout and stderr strings. Am able to do this but I find that if I want to capture both stdout and stderr strings I have to wait for the process to terminate before I can retrieve any output data. If I remove the stderr read I can capture the stdout data as its being emitted. Thus it appears that the stderr read "blocks" reading of stdout.

p.start

dim std_out as StreamReader = p.StandardOutput
dim std_err as StreamReader = p.StandardError

Do while DoneWithProcess = False
debug.Writeline(std_out.ReadLine)
debug.Writeline(std_err.ReadLine)
Loop
' Note that the flag DoneWithProcess is set in an event handler

Does anyone have any suggestions on how to "un block" the reading of the stderr strings?
Thanks,
bartj
 
You're calling ReadLine on std_err so of course it's going to wait there until a line is available, at which point it will be read and then you will go and read a line from from std_out. If you want to do two things at the same time then, in all cases, you must use two threads. Given that std_out is where most, and hopefully all, your data will be received, you might want to read that in the main thread, spawning a secondary thread to read std_err. If you need your main thread free for other things then you'll want to spawn a secondary thread for that too.
 
process

Thanks for your comments concerning reading stdout and stderr. Looks like its time to dive into threads. I have been doing vb5/6 programming for many years and have always managed to avoid the need for multiple threads. Thanks again.
 
It's very simple in this case.
VB.NET:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim p As Process = Process.Start("file name here")
    Dim output As New Threading.Thread(AddressOf ReadStream)
    Dim [error] As New Threading.Thread(AddressOf ReadStream)

    output.IsBackground = True
    [error].IsBackground = True

    output.Start(p.StandardOutput)
    [error].Start(p.StandardError)
End Sub

Private Sub ReadStream(ByVal stream As Object)
    Dim reader As IO.StreamReader = DirectCast(stream, IO.StreamReader)

    Do
        Debug.WriteLine(reader.ReadLine())
    Loop
End Sub
That uses the same method to read both streams, so there's no specific way to identify which is which. To distinguish them you might want to use different methods for each stream, or you might want to pass in a more complex object, which contains the stream and also an identifier, e.g. a name.

Note also that, if you want to access the UI of your application to use the data you read then you'll have to use delegation, because you cannot access controls directly from a secondary thread. To that end, you may want to read this.
 
adding a useful bit to the barebone example, stop reading when stream is closed:
VB.NET:
Do
    Dim line As String = reader.ReadLine
    If line Is Nothing Then Exit Do
    Debug.WriteLine(line)
Loop
 
Back
Top