.NET 11 Process.RunAndCaptureText avoids the classic stdout/stderr deadlock
.NET 11 RC2 adds Process.RunAndCaptureText, which runs an external command, drains stdout and stderr together and returns both strings with the exit code. It removes the deadlock that the classic redirect-and-ReadToEnd pattern can hit on noisy tools. Anyone who shells out to git, ffmpeg or internal CLIs will want to know the new helpers and their timeout behavior.
Key points
- Process.RunAndCaptureText(fileName, args) reads stdout and stderr concurrently and returns a ProcessTextOutput.
- Arguments are passed as a list, so spaces and quotes need no manual escaping.
- A timeout is built in; when it expires the call throws TimeoutException.
- The ProcessStartInfo overload requires both streams redirected and UseShellExecute set to false.
- A non-zero exit code does not throw; your code decides what counts as failure.
- The APIs ship in .NET 11 and do not compile against the .NET 10 SDK.
Redirecting stdout and stderr and reading them one after another is a well-known way to deadlock when a child process writes a lot to the stream you are not reading. The child blocks on a full pipe, your code blocks waiting for the other stream, and the app hangs without an error. .NET 11 adds Process.RunAndCaptureText to System.Diagnostics, which drains both pipes at the same time and returns the output, error text and exit status in one result object.
Arguments are passed as a list, so quoting problems go away, and a timeout parameter is built in. The async version takes a CancellationToken. Timeouts and cancellations surface as exceptions in several cases, so error handling needs care. The APIs ship in the .NET 11 release candidate and do not exist in the .NET 10 SDK, so check your target before adopting them.
Real-world use
- A build tool that runs git status or dotnet commands and parses their output.
- A service that drives noisy CLI tools such as ffmpeg from an ASP.NET Core backend.
- A background worker that calls an external command with a hard timeout and cancellation token.
Why it matters
Hand-rolled Process code with redirected streams can hang on a noisy child, and this API removes that pattern. Because .NET 11 is still a release candidate, pin your SDK and recheck timeout and exception behavior before shipping.