getsentry / getsentry/sentry-dotnet

chore: Use .NET 11 Process APIs to simplify `dev.cs`

Open
#5,363 1 comment 0 reactions 0 assignees View on GitHub
.NET Next Major Repository Maintenance Task
Dominant language
C#
Stars
770
Forks
248
Avg merge
2d 22h
Merged PRs (30d)
51

Description

### Summary

.NET 11 adds new `Process` APIs, that enables "the pit of success" for one-shot Process invocations:
- https://devblogs.microsoft.com/dotnet/process-api-improvements-in-dotnet-11/
- https://github.com/dotnet/core/blob/main/release-notes/11.0/preview/preview2/api-diff/Microsoft.NETCore.App/11.0-preview2_System.Diagnostics.Process.md
- https://github.com/dotnet/core/blob/main/release-notes/11.0/preview/preview3/api-diff/Microsoft.NETCore.App/11.0-preview3_System.Diagnostics.Process.md
- https://github.com/dotnet/core/blob/main/release-notes/11.0/preview/preview4/api-diff/Microsoft.NETCore.App/11.0-preview4_System.Diagnostics.Process.md
- https://github.com/dotnet/core/blob/main/release-notes/11.0/preview/preview5/api-diff/Microsoft.NETCore.App/11.0-preview5_System.Diagnostics.Process.md

With these, we can simplify our file-based apps `dev.cs`.

### Detail

.NET 11 ships new one-shot `Process` APIs that make launching a process + waiting + capturing output a single deadlock-free call, so the hand-rolled process plumbing in [dev.cs](sentry-dotnet/dev.cs) can be deleted and replaced with them.

## The relevant .NET 11 APIs

New static methods on `System.Diagnostics.Process` (from the [devblog](https://devblogs.microsoft.com/dotnet/process-api-improvements-in-dotnet-11/)):

- **`Process.Run` / `Process.RunAsync`** — start, wait for exit, return a `ProcessExitStatus` (with `ExitCode`, `Canceled`, `Signal`). No output capture.
- **`Process.RunAndCaptureText` / `…Async`** — same, but returns `ProcessTextOutput` with `StandardOutput` / `StandardError` captured together via multiplexing (no manual stream-draining, no deadlock risk).

## Changes in `dev.cs`

`dev.cs` is a Cocona file-based CLI with two private helpers doing exactly what these APIs replace:

| Current helper (~80 lines) | Replace with |
|---|---|
| `RunProcessAsync` — builds `ProcessStartInfo`, `Start()`, `try/catch`, `WaitForExitAsync()`, returns `ExitCode` | `Process.RunAsync(fileName, args)` → `.ExitStatus.ExitCode` |
| `IsCommandAvailableAsync` — runs `which`/`where.exe`, manually drains both streams with `Task.WhenAll` to avoid deadlock, checks exit code | `Process.RunAsync(...)` (output is discarded anyway) or `RunAndCaptureTextAsync` if it wants the path |

The manual stream-draining `Task.WhenAll(ReadToEndAsync, ReadToEndAsync, WaitForExitAsync)` in `IsCommandAvailableAsync` (dev.cs:198-201) is a footgun the new API is designed to eliminate.

## Caveats worth flagging back to him

> [!CAUTION]
> **These are .NET 11 *preview* APIs** - likely need to do this in version sentry-dotnet v7

Contributor guide

Open the contributing guide

Research direction

Start in sentry-dotnet/dev.cs, focusing on the private RunProcessAsync and IsCommandAvailableAsync helpers, especially the manual stream-draining code around lines 198-201. Read the linked .NET 11 Process API documentation first, then replace the hand-rolled process handling with the applicable one-shot APIs while preserving exit-code and command-availability behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
cli
Issue type
Refactor
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.