ProcessStartInfo hanging on "WaitForExit"? Why?

c#, processstartinfo

Solution

The problem is that if you redirect `StandardOutput` and/or `StandardError` the internal buffer can become full. Whatever order you use, there can be a problem:

- If you wait for the process to exit before reading `StandardOutput` the process can block trying to write to it, so the process never ends.

- If you read from `StandardOutput` using ReadToEnd then your process can block if the process never closes `StandardOutput` (for example if it never terminates, or if it is blocked writing to `StandardError`).

The solution is to use asynchronous reads to ensure that the buffer doesn't get full. To avoid any deadlocks and collect up all output from both `StandardOutput` and `StandardError` you can do this:

EDIT: See answers below for how avoid an ObjectDisposedException if the timeout occurs.

using (Process process = new Process())
{
    process.StartInfo.FileName = filename;
    process.StartInfo.Arguments = arguments;
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;

    StringBuilder output = new StringBuilder();
    StringBuilder error = new StringBuilder();

    using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
    using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
    {
        process.OutputDataReceived += (sender, e) => {
            if (e.Data == null)
            {
                outputWaitHandle.Set();
            }
            else
            {
                output.AppendLine(e.Data);
            }
        };
        process.ErrorDataReceived += (sender, e) =>
        {
            if (e.Data == null)
            {
                errorWaitHandle.Set();
            }
            else
            {
                error.AppendLine(e.Data);
            }
        };

        process.Start();

        process.BeginOutputReadLine();
        process.BeginErrorReadLine();

        if (process.WaitForExit(timeout) &&
            outputWaitHandle.WaitOne(timeout) &&
            errorWaitHandle.WaitOne(timeout))
        {
            // Process completed. Check process.ExitCode here.
        }
        else
        {
            // Timed out.
        }
    }
}

Problem

I have the following code: ``` info = new System.Diagnostics.ProcessStartInfo("TheProgram.exe", String.Join(" ", args)); info.CreateNoWindow = true; info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; info.RedirectStandardOutput = true; info.UseShellExecute = false; System.Diagnostics.Process p = System.Diagnostics.Process.Start(info); p.WaitForExit(); Console.WriteLine(p.StandardOutput.ReadToEnd()); //need the StandardOutput contents ``` I know that the output from the process I am starting is around 7MB long. Running it in the Windows console works fine. Unfortunately programmatically this hangs indefinitely at `WaitForExit`. Note also this code does NOT hang for smaller outputs (like 3KB). Is it possible that the internal `StandardOutput` in `ProcessStartInfo` can't buffer 7MB? If so, what should I do instead? If not, what am I doing wrong?

Original source

Related problems