Skip to content

Add Process constructor accepting SafeProcessHandle and optional stream handles#128491

Draft
Copilot wants to merge 4 commits into
mainfrom
copilot/add-safe-handle-support-to-process
Draft

Add Process constructor accepting SafeProcessHandle and optional stream handles#128491
Copilot wants to merge 4 commits into
mainfrom
copilot/add-safe-handle-support-to-process

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 22, 2026

Description

Adds a new public Process constructor that creates instances from user-provided safe handles, enabling advanced interop scenarios where users call CreateProcess (or equivalent) directly but still want Process class features like async stream reading and WaitForExit.

API Addition

public Process(
    SafeProcessHandle processHandle,
    SafeFileHandle? standardInput = null,
    SafeFileHandle? standardOutput = null,
    SafeFileHandle? standardError = null,
    ProcessStartInfo? startInfo = null)

On Windows, standardOutput and standardError handles must be opened for asynchronous I/O (IsAsync == true); an ArgumentException is thrown otherwise.

Changes

  • Ref assembly (ref/System.Diagnostics.Process.cs): New constructor signature
  • Implementation (Process.cs): Constructor wires up handle, process ID, and wraps optional file handles into StreamWriter/StreamReader using existing OpenStream + encoding logic. Validates that standardOutput/standardError handles are async on Windows.
  • Tests (ProcessHandlesTests.Windows.cs):
    • Refactored RunWithInvalidHandlesRunWithHandles parameterized by handle values and bInheritHandles
    • Extracted CreateProcessWithHandles static helper that encapsulates the CreateProcess P/Invoke logic, reused by both RunWithHandles and the new test
    • Added INVALID_HANDLE_VALUE constant to replace magic numbers
    • Added ProcessStartedWithAnonymousPipeHandles_CanCaptureOutput test: creates async anonymous pipes via SafeFileHandle.CreateAnonymousPipe(asyncRead: true), enables inheritance via SetHandleInformation, spawns child process using the shared helper, wraps read handles in new Process ctor, uses ReadAllText() to assert captured stdout/stderr
  • Test project (.csproj): Added Interop.HandleInformation.cs common source
  • Resources (Strings.resx): Added Argument_HandleNotAsync error message

Usage Example

SafeFileHandle.CreateAnonymousPipe(out SafeFileHandle readHandle, out SafeFileHandle writeHandle, asyncRead: true);
// ... CreateProcess with writeHandle as hStdOutput ...

using Process process = new(safeProcessHandle, standardOutput: readHandle);
(string stdout, string stderr) = process.ReadAllText();

Copilot AI and others added 2 commits May 22, 2026 15:22
…ream handles

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3a2f55b9-2cc6-46ba-87af-1dc53029c488

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
…unused usings

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3a2f55b9-2cc6-46ba-87af-1dc53029c488

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 22, 2026 15:49
Copilot AI review requested due to automatic review settings May 22, 2026 15:49
Copy link
Copy Markdown
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback

Comment thread src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs Outdated
Comment thread src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.Windows.cs Outdated
Comment thread src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.Windows.cs Outdated
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process
See info in area-owners.md if you want to be subscribed.

…ANDLE_VALUE, extract CreateProcessWithHandles helper

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/12cdb475-8f8c-4309-b5d7-d0b02c675048

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot May 22, 2026 16:19
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 22, 2026

@copilot address my feedback

Done in a53a1fc. All three items addressed:

  • Simplified _startInfo assignment (removed unnecessary null check)
  • Used INVALID_HANDLE_VALUE constant instead of (nint)(-1) magic numbers
  • Extracted CreateProcessWithHandles helper that's reused by both RunWithHandles and the new test

Copilot AI requested a review from adamsitnik May 22, 2026 16:20
Copy link
Copy Markdown
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot address my feedback

Comment thread src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.Windows.cs Outdated
Comment thread src/libraries/System.Diagnostics.Process/tests/ProcessHandlesTests.Windows.cs Outdated
… Windows

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/b6feaf9e-a3a5-4056-a01a-9aa9761be8be

Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot May 22, 2026 17:18
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 22, 2026

@copilot address my feedback

Done in a6488fc. Changes:

  • Added asyncRead: true to CreateAnonymousPipe calls
  • Replaced ReadToEnd with process.ReadAllText()
  • Added IsAsync validation for standardOutput/standardError on Windows (throws ArgumentException if not async)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants