Asmichi.ChildProcess 0.15.0

dotnet add package Asmichi.ChildProcess --version 0.15.0
NuGet\Install-Package Asmichi.ChildProcess -Version 0.15.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Asmichi.ChildProcess" Version="0.15.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Asmichi.ChildProcess --version 0.15.0
#r "nuget: Asmichi.ChildProcess, 0.15.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Asmichi.ChildProcess as a Cake Addin
#addin nuget:?package=Asmichi.ChildProcess&version=0.15.0

// Install Asmichi.ChildProcess as a Cake Tool
#tool nuget:?package=Asmichi.ChildProcess&version=0.15.0

日本語

Asmichi.ChildProcess

A .NET library that provides functionality for creating child processes. Easier, less error-prone, more flexible than System.Diagnostics.Process at creating and interacting with child processes.

This library can be obtained via NuGet.

Build Status

See the Wiki for the goals and the roadmap.

Comparison with System.Diagnostics.Process

  • Concentrates on creating a child process and obtaining its output.
    • Cannot query status of a process.
    • Cannot create a resident process.
  • More destinations of redirection:
    • NUL
    • File (optionally appended)
    • Pipe
    • Handle
  • Less error-prone default values for redirection:
    • stdin to NUL
    • stdout to the current stdout
    • stderr to the current stderr
  • Pipes are asynchronous; asynchronous reads and writes will be handled by IO completion ports.
  • Ensures termination of child processes

License

The MIT License

Supported Runtimes

  • .NET Core 3.1 or later

RIDs:

  • win10-x86 (not tested)
  • win10-x64 (1809 or later; tested on 1809)
  • win10-arm (not tested)
  • win10-arm64 (not tested)
  • linux-x64 (tested on Ubuntu 18.04)
  • linux-arm (not tested)
  • linux-arm64 (not tested)
  • linux-musl-arm64 (not tested)
  • linux-musl-x64 (tested on Alpine 3.13)
  • osx-x64 (macOS 10.15 Catalina or later; tested on 11)
  • osx-arm64 (macOS 11.0 Big Sur or later; not tested)

NOTE: On glibc-based Linux, the system must have glibc 2.27 or later and libstdc++ 3.4.25 or later.

Known Issues

  • On Windows 10 1809 (including Windows Server 2019), SignalTermination just forcibly kills the process tree (the same operation as Kill).
    • This is due to a Windows pseudoconsole bug where ClosePseudoConsole does not terminate applications attached to the pseudoconsole.
  • On macOS prior to 11.0, ExitCode for processes killed by a signal will always be -1.
    • This is due to a waitid bug where it returns 0 in siginfo_t.si_status for such processes.

Notes

  • When completely rewriting environment variables with ChildProcessCreationContext or ChildProcessFlags.DisableEnvironmentVariableInheritance, it is recommended that you include basic environment variables such as SystemRoot, etc.

Limitations

  • More than 2^63 processes cannot be created.

Assumptions on Runtimes

This library assumes that the underlying runtime has the following characteristics:

  • Windows
    • The inner value of a SafeFileHandle is a file handle.
    • The inner value of a SafeWaitHandle is a handle that WaitForSingleObject can wait for.
    • The inner value of a SafeProcessHandle is a process handle.
  • *nix
    • The inner value of a SafeFileHandle is a file descriptor.
    • The inner value of a SafeProcessHandle is a process id.
    • Socket.Handle returns a socket file descriptor.

Examples

Open ChildProcessExample.sln or see ChildProcess.Example for more examples.

Basic

You can read the output of a child, optionally combining stdout and stderr.

var si = new ChildProcessStartInfo("cmd", "/C", "echo", "foo")
{
    StdOutputRedirection = OutputRedirection.OutputPipe,
    // Works like 2>&1
    StdErrorRedirection = OutputRedirection.OutputPipe,
};

using (var p = ChildProcess.Start(si))
{
    using (var sr = new StreamReader(p.StandardOutput))
    {
        // "foo"
        Console.Write(await sr.ReadToEndAsync());
    }
    await p.WaitForExitAsync();
    // ExitCode: 0
    Console.WriteLine("ExitCode: {0}", p.ExitCode);
}

Redirection to File

You can redirect the output of a child into a file without ever reading the output.

var si = new ChildProcessStartInfo("cmd", "/C", "set")
{
    ExtraEnvironmentVariables = new Dictionary<string, string> { { "A", "A" } },
    StdOutputRedirection = OutputRedirection.File,
    StdErrorRedirection = OutputRedirection.File,
    StdOutputFile = "env.txt",
    StdErrorFile = "env.txt",
    Flags = ChildProcessFlags.UseCustomCodePage,
    CodePage = Encoding.Default.CodePage, // UTF-8
};

using (var p = ChildProcess.Start(si))
{
    await p.WaitForExitAsync();
}

// A=A
// ALLUSERSPROFILE=C:\ProgramData
// ...
Console.WriteLine(File.ReadAllText("env.txt"));

True piping

You can pipe the output of a child into another child without ever reading the output.

// Create an anonymous pipe.
using var inPipe = new AnonymousPipeServerStream(PipeDirection.In);

var si1 = new ChildProcessStartInfo("cmd", "/C", "set")
{
    // Connect the output to writer side of the pipe.
    StdOutputRedirection = OutputRedirection.Handle,
    StdErrorRedirection = OutputRedirection.Handle,
    StdOutputHandle = inPipe.ClientSafePipeHandle,
    StdErrorHandle = inPipe.ClientSafePipeHandle,
    Flags = ChildProcessFlags.UseCustomCodePage,
    CodePage = Encoding.Default.CodePage, // UTF-8 on .NET Core
};

var si2 = new ChildProcessStartInfo("findstr", "Windows")
{
    // Connect the input to the reader side of the pipe.
    StdInputRedirection = InputRedirection.Handle,
    StdInputHandle = inPipe.SafePipeHandle,
    StdOutputRedirection = OutputRedirection.OutputPipe,
    StdErrorRedirection = OutputRedirection.OutputPipe,
    Flags = ChildProcessFlags.UseCustomCodePage,
    CodePage = Encoding.Default.CodePage, // UTF-8 on .NET Core
};

using var p1 = ChildProcess.Start(si1);
using var p2 = ChildProcess.Start(si2);

// Close our copy of the pipe handles. (Otherwise p2 will get stuck while reading from the pipe.)
inPipe.DisposeLocalCopyOfClientHandle();
inPipe.Close();

using (var sr = new StreamReader(p2.StandardOutput))
{
    // ...
    // OS=Windows_NT
    // ...
    Console.Write(await sr.ReadToEndAsync());
}

await p1.WaitForExitAsync();
await p2.WaitForExitAsync();
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.1 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETCoreApp 3.1

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Asmichi.ChildProcess:

Package Downloads
OneWare.Essentials

Essentials Needed for One Ware Plugin Development

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.15.0 107 3/16/2024
0.14.0 1,927 5/3/2023
0.13.0 604 6/19/2022
0.12.0 509 2/23/2022
0.11.0 518 9/14/2021
0.10.0 291 8/31/2021
0.9.0 320 7/28/2021
0.8.0 382 7/3/2021
0.7.0 316 6/8/2021
0.6.0 404 2/28/2021
0.5.2 364 2/23/2021
0.4.0 346 2/14/2021
0.3.0 434 11/25/2020
0.2.0 492 10/17/2020
0.1.0 627 5/1/2019