Exploring the New Process API Enhancements in .NET 11

By • min read

The System.Diagnostics.Process class has long been the go‑to way for creating and interacting with processes in .NET. With .NET 11, this class receives its largest update in years, adding high‑level APIs that simplify starting processes and capturing output without deadlocks, give you full control over handle inheritance and standard stream redirection, introduce lifetime management features like KillOnParentExit, and offer a lightweight SafeProcessHandle‑based surface that is more trimmer‑friendly. Below, we answer the most pressing questions about these improvements.

What new one‑liner APIs simplify starting and waiting for processes?

Two new methods let you start a process and wait for it to finish in a single call, drastically reducing boilerplate code. Process.RunAndCaptureText[Async] starts a process, captures both standard output and error streams, and waits for exit – all in one go. This is perfect for scripts or tools that need to run an external command and get its result without worrying about manual stream handling. For scenarios where you don’t need the output, Process.Run[Async] simply starts the process and waits for exit. Both methods are available in synchronous and asynchronous variants, making them easy to integrate into any codebase. They automatically avoid deadlocks by using the underlying multiplexing logic designed for output capture.

Exploring the New Process API Enhancements in .NET 11
Source: devblogs.microsoft.com

How does the fire‑and‑forget API work for background processes?

When you only need to know the process ID (PID) of a started process and don’t want to manage its lifecycle, Process.StartAndForget is the answer. This method starts a process, immediately returns its PID, and releases all .NET resources tied to the process object. The child process continues running independently. This is ideal for launching long‑running background tasks or services where you don’t need to wait for exit or capture output. Because the Process instance is disposed right away, memory usage is minimal. You can later use the returned PID with system‑level tools or the SafeProcessHandle APIs if you ever need to kill or query the process.

How does .NET 11 prevent deadlocks when reading process output?

One of the most frustrating issues in earlier versions was deadlocking when reading both stdout and stderr from a process. .NET 11 introduces Process.ReadAllText/Bytes/Lines[Async] methods that read both streams simultaneously using internal multiplexing. These methods avoid pipe buffer deadlocks because they consume stdout and stderr in parallel, never letting either buffer fill up completely. The result is a clean, reliable way to capture the full output of a process without hanging. For advanced scenarios, you can also combine these with the new ProcessStartInfo.Standard[Input/Output/Error]Handle properties to redirect streams to files, pipes, or any SafeFileHandle – and still avoid deadlocks by using the multiplexed readers.

What control do we now have over handle inheritance for child processes?

In the past, managing which handles a child process inherits could be error‑prone, often leading to accidental leaks of sensitive handles. .NET 11 introduces ProcessStartInfo.InheritedHandles, a property that lets you specify exactly which SafeFileHandle instances should be inherited by the child process. By default, no handles are inherited unless explicitly listed. This gives you precise control: you can, for example, pass only a specific pipe handle while keeping all other handles private. The inheritance model works on both Windows and Linux, making cross‑platform code much safer. Combined with the new File.OpenNullHandle() method (which discards writes and returns EOF on reads), you can easily redirect streams to “nowhere” while still controlling inheritance.

What is the KillOnParentExit feature and how does it work?

ProcessStartInfo.KillOnParentExit ensures that when the parent process terminates (normally or abnormally), all child processes launched with this option are automatically killed. This is available on both Windows and Linux. Under the hood, .NET 11 uses platform‑specific mechanisms: on Windows it leverages job objects; on Linux it uses prctl with PR_SET_PDEATHSIG. This feature is invaluable for short‑lived tools, server applications, or any scenario where you want to guarantee that child processes don’t survive the parent. It pairs well with the StartDetached option, which does the opposite – starts a process that survives the parent’s exit. Together, they give you full lifecycle control.

Exploring the New Process API Enhancements in .NET 11
Source: devblogs.microsoft.com

How can I start a process that lives on after the parent exits?

Sometimes you need a child process to continue running even after the parent process terminates, for example, when launching a background updater or a detached UI component. .NET 11 introduces ProcessStartInfo.StartDetached – set it to true and the child process will not be killed when the parent exits, receives a signal, or closes its terminal. This works on both Windows and Linux by detaching the child from the parent’s process group or job. Combined with the fire‑and‑forget StartAndForget method, you can quickly launch a persistent background process whose PID you can store for later management (e.g., using SafeProcessHandle).

What is the SafeProcessHandle API and why is it useful?

The SafeProcessHandle class provides a lightweight, trimmer‑friendly alternative to the full Process object. It includes static methods like Start (to create a process), WaitForExit, Kill, and Signal. This API surface is much smaller than Process, making it ideal for applications that need to minimise binary size (e.g., NativeAOT). Compared to .NET 10, NativeAOT binaries that use Process can be up to 20% smaller; those using SafeProcessHandle can be up to 32% smaller. The handle itself is a safe wrapper around the underlying OS process handle, and you can use it to perform core process operations without allocating the larger Process object. For even more detail, see the ProcessExitStatus structure, which reports exit code, terminating signal (on Unix), and whether the process was killed due to timeout or cancellation.

How do the new anonymous pipe and null handle APIs simplify stream redirection?

Working with streams in process communication is easier than ever thanks to two new additions. SafeFileHandle.CreateAnonymousPipe creates a connected pair of pipe handles (read end and write end), with optional asynchronous I/O support. You can directly assign these handles to ProcessStartInfo.StandardInputHandle, StandardOutputHandle, or StandardErrorHandle to redirect streams without dealing with Process.StartInfo.RedirectStandardOutput etc. Additionally, File.OpenNullHandle() returns a handle that discards all writes and returns EOF on reads – perfect for ignoring output or error streams cleanly. These low‑level improvements work hand in hand with the other new APIs to give you full flexibility in stream redirection, all while keeping the code trim and efficient.

Recommended

Discover More

10 Powerful Features in MerMark Editor v0.2.0 You Should Know AboutThe Interview Method: Using LLMs to Extract Human ExpertiseBiotech Career Moves: Q&A on the Latest Executive AppointmentsHow to Investigate Mysterious 'Little Red Dots' from JWST Using X-Ray DataNetBSD 11.0 Poised for Final Release: RC4 Marks the Last Testing Milestone