Skip to content

[API Proposal]: Process constructor from SafeProcessHandle #71595

@NN---

Description

@NN---

Background and motivation

There are plenty of ways to create a process where .NET does not support this or where there is already a process handle from native method.
Currently there is no possibility to create a .NET Process object from the SafeProcessHandle.

API Proposal

namespace System.Runtime.InteropServices;

[SupportedOSPlatform("windows")]
public ref struct WindowsProcessStartArguments
{
    public WindowsProcessStartArguments();

    public unsafe char* Arguments { get; }
    public unsafe char* EnvironmentVariables{ get; }

    public ProcessStartInfo ProcessStartInfo { get; }
    public nint StandardError { get; }
    public nint StandardInput { get; }
    public nint StandardOutput { get; }

    public static Process Start(ProcessStartInfo startInfo, Func<WindowsProcessStartArguments, SafeProcessHandle> callback);
    public static Process Start<TState>(ProcessStartInfo startInfo, Func<WindowsProcessStartArguments, TState, SafeProcessHandle> callback, TState state);
}

[UnsupportedOSPlatform("windows")]
public ref struct UnixProcessStartArguments
{
    public UnixProcessStartArguments();

    public unsafe byte* ResolvedPath { get; }
    public unsafe byte** Arguments { get; }
    public unsafe byte** EnvironmentVariables { get; }

    public ProcessStartInfo ProcessStartInfo { get; }
    public nint StandardError { get; }
    public nint StandardInput { get; }
    public nint StandardOutput { get; }

    [UnsupportedOSPlatform("ios")]
    [UnsupportedOSPlatform("tvos")]
    [UnsupportedOSPlatform("maccatalyst")]
    public static Process Start(ProcessStartInfo startInfo, Func<UnixProcessStartArguments, SafeProcessHandle> callback);
    [UnsupportedOSPlatform("ios")]
    [UnsupportedOSPlatform("tvos")]
    [UnsupportedOSPlatform("maccatalyst")]
    public static Process Start<TState>(ProcessStartInfo startInfo, Func<UnixProcessStartArguments, TState, SafeProcessHandle> callback, TState state);
}

API Usage

ProcessStartInfo startInfo = new("cmd")
{
    ArgumentList = { "/c", "echo hello && echo error 1>&2" },
    RedirectStandardOutput = true,
    RedirectStandardError = true
};

using Process process = WindowsProcessStartArguments.Start(startInfo, (WindowsProcessStartArguments args) =>
{
    Interop.Kernel32.STARTUPINFOEX startupInfoEx = default;
    Interop.Kernel32.PROCESS_INFORMATION processInfo = default;
    Interop.Kernel32.SECURITY_ATTRIBUTES unused_SecAttrs = default;

    startupInfoEx.StartupInfo.cb = sizeof(Interop.Kernel32.STARTUPINFOEX);
    startupInfoEx.StartupInfo.hStdInput = args.StandardInput;
    startupInfoEx.StartupInfo.hStdOutput = args.StandardOutput;
    startupInfoEx.StartupInfo.hStdError = args.StandardError;
    startupInfoEx.StartupInfo.dwFlags = Interop.Advapi32.StartupInfoOptions.STARTF_USESTDHANDLES;

    bool retVal = Interop.Kernel32.CreateProcess(
        null,
        (char*)args.Arguments,
        ref unused_SecAttrs,
        ref unused_SecAttrs,
        bInheritHandles: true,
        Interop.Kernel32.EXTENDED_STARTUPINFO_PRESENT,
        (char*)args.EnvironmentVariables,
        null,
        &startupInfoEx,
        &processInfo
    );

    if (!retVal)
    {
        throw new Win32Exception();
    }

    Interop.Kernel32.CloseHandle(processInfo.hThread);

    return new SafeProcessHandle(processInfo.hProcess, ownsHandle: true);
});

Alternative Designs

The alternative design included a ctor, but it was too fragile. Check #128491 for details

Risks

Can't see any as of now, as BCL takes care of removing all known risks before invoking the callback.

Working prototype: #128862

Metadata

Metadata

Assignees

Labels

api-ready-for-reviewAPI is ready for review, it is NOT ready for implementationarea-System.Diagnostics.Processin-prThere is an active PR which will close this issue when it is merged

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions