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?