getsentry / getsentry/sentry-dotnet
chore: Use .NET 11 Process APIs to simplify `dev.cs`
- 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
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