57

I'm trying to capture process output in "realtime" (while it's running). The code I use is rather simple (see below). For some strange reason the OutputDataReceived event is never called. Why?

private void button2_Click(object sender, EventArgs e)
    {
      // Setup the process start info
      var processStartInfo = new ProcessStartInfo("ping.exe", "-t -n 3 192.168.100.1")
      {
        UseShellExecute = false,
        RedirectStandardOutput = true
      };

      // Setup the process
      mProcess = new Process { StartInfo = processStartInfo, EnableRaisingEvents = true };

      // Register event
      mProcess.OutputDataReceived += OnOutputDataReceived;

      // Start process
      mProcess.Start();
      mProcess.WaitForExit();
    }

    void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
    {
       //Never gets called...
    }
Boris
  • 8,551
  • 25
  • 67
  • 120

2 Answers2

107

You need to call

mProcess.BeginOutputReadLine();

BeginOutputReadLine - "Begins asynchronous read operations on the redirected StandardOutput stream of the application."

Chris
  • 27,210
  • 6
  • 71
  • 92
  • 14
    In addition, the external proces is required to flush its output buffer at the moment it outputs something. Without flushing, the output buffer could last until the external process is exited; this makes it impossible for the main application to capture the output "live". – halfpastfour.am May 07 '13 at 16:52
  • 1
    @BobKruithof: true enough. The external process does need to actually send the data but without any other information its easiest to keep to the question asked. :) – Chris May 08 '13 at 15:40
  • 3
    Also, some applications are writing into standard ERROR instead of standard OUTPUT. Usually you cannot make a difference when looking at the output manually. So, try to add just in case: "RedirectStandardError = true" and "mProcess.BeginErrorReadLine();", respectively. – altumano Mar 24 '14 at 18:37
  • @altumano: a little tangential but if you did want to capture things from the ERROR stream then you would of course most importantly have to bind to the `ErrorDataReceived` event. :) – Chris Mar 24 '14 at 19:16
  • 22
    Note that this call needs to go *after* `mProcess.Start()`. Output will be preserved between the two calls. –  Sep 26 '14 at 16:51
3

void ExecuteCommand(string cmdpath, string cmdargs)
{
    string command = cmdpath + " " + cmdargs;

    tabc_results.SelectTab(1); 
    DoConsole("\r\nCmd>> " + command + "\r\n");

    var processInfo = new System.Diagnostics.ProcessStartInfo("cmd.exe", "/c " + command);
    processInfo.CreateNoWindow = true;
    processInfo.UseShellExecute = false;
    processInfo.RedirectStandardError = true;
    processInfo.RedirectStandardOutput = true;

    var process = System.Diagnostics.Process.Start(processInfo);

    process.OutputDataReceived += (
        object sender, System.Diagnostics.DataReceivedEventArgs e
    ) => DoConsole("stdout>>  " + e.Data + "\r\n");
    //Console.WriteLine("output>>" + e.Data);
    process.BeginOutputReadLine();

    process.ErrorDataReceived += (
        object sender, System.Diagnostics.DataReceivedEventArgs e
    ) =>DoConsole("stderr>>  " + e.Data + "\r\n");
    //Console.WriteLine("error>>" + e.Data);
    process.BeginErrorReadLine();

    process.WaitForExit();

    DoConsole("retcode>> " + process.ExitCode.ToString() + "\r\n");
    //Console.WriteLine("ExitCode: {0}", process.ExitCode);
    process.Close();
}
JohnLBevan
  • 22,735
  • 13
  • 96
  • 178
guest1
  • 49
  • 1