1

I'm using the data ready events of the Process class to get information from the standard output and standard error of a running process.

It works great on the first run, but after calling Stop() then Start() to force a restart of the application, I no longer recieve data. I've tried CancelErrorRead() but no luck there.

I'm considering just re-instantiating the object every time I need to re-run the app, but it seems silly to need to do that.

Any advice on how to re-use a Process object to restart a stopped process?

Relevant code chunks:

Constructor:

   ProcessStartInfo objStartInfo = new ProcessStartInfo();
    objStartInfo.CreateNoWindow = true;
    objStartInfo.RedirectStandardInput = true;
    objStartInfo.RedirectStandardOutput = true;
    objStartInfo.RedirectStandardError = true;
    objStartInfo.UseShellExecute = false;

    objClient = new Process();
    objClient.StartInfo = objStartInfo;

    objClient.EnableRaisingEvents = true;
    objClient.OutputDataReceived   += new DataReceivedEventHandler(read);
    objClient.ErrorDataReceived    += new DataReceivedEventHandler(error);

Start:

    objClient.StartInfo.FileName    = strAppPath;
    objClient.StartInfo.Arguments   = strArgs;
    start();
    objClient.BeginErrorReadLine();
    objClient.BeginOutputReadLine();

Stop:

    objClient.Close();
    objClient.CancelErrorRead();
    objClient.CancelOutputRead();
RandomInsano
  • 1,204
  • 2
  • 16
  • 36

2 Answers2

1

Your Process object is not associated with a process until you call Start() (or use one of the static methods off Process). A stopped/closed process is functionally the same as no process at all. Given that, it's hard to believe there's any overhead to creating a new Process object, when compared to the (relatively enormous) cost of creating processes on Windows. Just create new Process objects as needed.

Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
  • That's a good call. Is there a way to see if the garbage collector cleans up my objects? Do I need to remove the event handlers before it will be collected? I think that's the case in JavaScript. – RandomInsano Nov 03 '09 at 22:28
  • It's probably true that creating a new Process object each time is not that expensive but I think that's not the solution. Getting around the problem like that may cause unexpected behaviour afterwards. Given the code sample and documentation, calls to BeginOutputReadLine and BeginErrorReadLine are missing. – Mehmet Ergut Nov 03 '09 at 22:29
  • @Mehmet: agreed your recommendations are good, but the above is not "working around the problem", it's the correct way to interface with processes in .NET. – Michael Petrotta Nov 03 '09 at 22:36
  • @RandomInsano: It's good practice to remove your event handlers, but it's not necessary in this case. see http://stackoverflow.com/questions/298261/do-event-handlers-stop-garbage-collection-from-occuring – Michael Petrotta Nov 03 '09 at 22:59
  • @Michael Petrotta - Thanks. Good reading @All - Updated code to include the BeginErrorReadLine stuff. Forgot to add that before. – RandomInsano Nov 03 '09 at 23:04
  • @Michael: didn't mean to sound harsh, got stuck on the missing method calls, it's late over here :| On second thought, it may be that the Process class not reinitializing correctly the asynchronous streams once it's closed. – Mehmet Ergut Nov 03 '09 at 23:25
0

According to msdn you should call BeginOutputReadLine and BeginErrorReadLine to enable asynchronous reads from StandardOutput or StandardError using events.

Have a look at the remarks section on BeginOutputReadLine

Mehmet Ergut
  • 1,034
  • 8
  • 9
  • Indeed I do! I seem to have forgotten to paste those in there. The problem is that those two functions can be called only once, a second call throws an exception, and calling CancelErrorRead() before calling them again doesn't really allow me to recapture the outputs. – RandomInsano Nov 03 '09 at 22:27
  • Looks like creating new Process objects is the only way out as Michael suggested. – Mehmet Ergut Nov 03 '09 at 23:32