views:

114

answers:

2

Hi, I've been searching around the net for roughly three hours now w/o getting forward. I don't know VB very well, but I need to create a wrapper program for any executable that logs the arguments, all input, output and err information:

  • My wrapper is called: e.g. someApp.exe arg1 arg2
  • Logs to someApp.log: arg1 arg2
  • Calls original executable: _someApp.exe arg1 arg2
  • Must log and forward any console input to _someApp process inputstream
  • Must log any output and error stream from _someApp process

Okay, I'm stuck at point 4 now:

        Dim p As New ProcessStartInfo
        p.FileName = execute
        p.Arguments = Command()
        p.UseShellExecute = False
        p.CreateNoWindow = True
        p.RedirectStandardInput = True
        p.RedirectStandardError = True
        p.RedirectStandardOutput = True

        Dim process As System.Diagnostics.Process
        process = Diagnostics.Process.Start(p)
        process.WaitForExit()

After _someApp ends I am able to read out and err stream to log it, but I still need to provide my own wrappers input to the process and I want to read out and err stream as it happens.

Thanks for info/examples

A: 

How about for writing to the app:

Dim sw as IO.StreamWriter = process.StandardInput
sw.WriteLine("Boo")

and for reading from the standard output:

Dim sr As IO.StreamReader = process.StandardOutput
Do
  aString = sr.ReadLine()
Loop Until (sr.EndOfStream)
RobS
Yes, I know I can write to and read from the process, but I need to write my applications input as it happens to the process inputstream and I need to read from process out and err stream as it happens. Thanks anyway
GHad
I see now. Then why are you calling process.waitForExit()? According to the docs this halts the program indefintely until the process has exited. I don't think you want to to that.
RobS
Yes I know that, but at the moment this is the only way I know of to read out and err streams: after the program has exited. I need a way to read that streams in an extra thread or something like this, non-blocking is the key. But I don't know how to make such threads in VB, because I'm rather noobish at that subject. Greetz, Ghad
GHad
A: 

Okay here the solution...

Variables needed:

Private process As System.Diagnostics.Process

Private threadOut As Thread

Private streamOut As System.IO.StreamReader

Private threadErr As Thread

Private streamErr As System.IO.StreamReader

Private threadIn As Thread

Private streamIn As System.IO.StreamWriter

Subs needed:

Private Sub ThreadTaskOut()
    Dim line
    While Not process.HasExited
        line = streamOut.ReadToEnd
        If line <> Nothing And line <> "" Then
            log("Out: " & line)
            Console.Out.Write(line)
        End If
    End While
End Sub

Private Sub ThreadTaskErr()
    Dim line
    While Not process.HasExited
        line = streamErr.ReadToEnd
        If line <> Nothing And line <> "" Then
            log("Err: " & line)
            Console.Error.Write(line)
        End If
    End While
End Sub

Private Sub ThreadTaskIn()
    Dim line
    While Not process.HasExited
        line = Console.In.ReadLine
        If line <> Nothing And line <> "" Then
            log("In: " & line)
            streamIn.WriteLine(line)
        End If
    End While
End Sub

Inside main:

        ' create process information
        Dim p As New ProcessStartInfo
        p.FileName = execute
        p.Arguments = Command()
        p.UseShellExecute = False
        p.CreateNoWindow = True
        p.RedirectStandardInput = True
        p.RedirectStandardError = True
        p.RedirectStandardOutput = True

        ' log process start
        log("Execute: " & execute & " " & Command())

        ' start process
        process = Diagnostics.Process.Start(p)

        ' start thread for output stream
        streamOut = process.StandardOutput
        threadOut = New Thread(AddressOf ThreadTaskOut)
        threadOut.IsBackground = True
        threadOut.Start()

        ' start thread for error stream
        streamErr = process.StandardError
        threadErr = New Thread(AddressOf ThreadTaskErr)
        threadErr.IsBackground = True
        threadErr.Start()

        ' start thread for input stream
        streamIn = process.StandardInput
        threadIn = New Thread(AddressOf ThreadTaskIn)
        threadIn.IsBackground = True
        threadIn.Start()

        ' wait for the process to finish
        process.WaitForExit()

log is another sub to log to file, execute is the variable holding the _someApp.exe frommy initial post. I still don't know if the console to inputstream thread dows it right, because my wrapped app had no input as it seems. May someone spotts an error...

For my purposes, hmm it works like I need it

Greetz, GHad

Code inside main

GHad
Be sure to read the docs regarding RedirectStandardOutput and RedirectStandardError about a potential deadlock that can occur when you redirect both.
Chris Dunaway
Thanks for the suggestion. I already read those parts, but I did not understand it completly. But I think I also read, you can do it in threads without a deadlock. So that is why I'm using them, there should not be any deadlock afaik. Greetz, GHad
GHad