MedallionShell Documentation

repository·master·Indexed 19 days ago

https://github.com/madelson/medallionshell

A .NET library providing a high-level wrapper around System.Diagnostics.Process to simplify process management. It features async/await integration, standard IO piping via method chaining or operators (<, |, >), cross-platform signal handling, and the Shell class for reusing command configurations.

Tokens
2K
Snippets
7
Records
7
Agent score
16%

What's inside MedallionShell

  1. Handle Standard IO streams

    master

    MedallionShell captures standard error and standard output by default in the CommandResult. You can access these via result.StandardOutput and result.StandardError after the command completes.

    Consuming output as a merged stream

    To process stdout and stderr as a single interleaved stream of lines (similar to a console), use GetOutputAndErrorLines().

    Direct stream interaction

    You can interact with Command.StandardInput, Command.StandardOutput, and Command.StandardError directly. These expose TextWriter/TextReader for text and BaseStream for raw bytes.

    Warning: Any content you read directly from these streams will not be included in the result.StandardOutput or result.StandardError properties. The result properties only store content that has not been consumed by other mechanisms.

    // 1. Accessing captured output from result
    var command = Command.Run("ls");
    var result = await command.Task;
    Console.WriteLine(result.StandardOutput);
    
    // 2. Consuming merged lines
    foreach (var line in command.GetOutputAndErrorLines())
    {
        Console.WriteLine(line);
    }
    
    // 3. Direct stream interaction (Text and Bytes)
    command.StandardInput.Write("some text");
    command.StandardInput.BaseStream.Write(new byte[100]);
    string line = command.StandardOutput.ReadLine();
  2. Use Shells to reuse command configurations

    master

    If you need to run multiple commands with the same configuration (e.g., same working directory, timeout, or error handling), use a Shell object. A Shell acts as a factory for Command instances with pre-applied options.

    // Define a reusable shell with specific settings
    private static readonly Shell MyShell = new Shell(options => 
        options.ThrowOnError().Timeout(TimeSpan.FromMinutes(5))
    );
    
    // Use the shell to run commands
    var command = MyShell.Run("foo.exe", new[] { "arg1" });
  3. Pipe IO between commands and files

    master

    MedallionShell provides powerful ways to handle data flow between processes and external sources/sinks.

    Piping using methods

    You can use RedirectFrom and PipeTo to chain commands or redirect to/from files. This returns a new Command instance that represents the entire operation.

    Piping using operators

    MedallionShell supports operator overloading to mimic command-line syntax:

    • < for redirection from a source (e.g., a file).
    • | for piping from one command to another.
    • > for redirection to a sink (e.g., a file).

    Stream piping

    Standard IO streams support PipeFromAsync and PipeToAsync for common sources like FileInfo, Stream, TextReader/Writer, and collections.

    // Using method chaining
    await Command.Run("processingStep1.exe")
        .RedirectFrom(new FileInfo("input.txt"))
        .PipeTo(Command.Run("processingStep2.exe"))
        .RedirectTo(new FileInfo("output.txt"));
    
    // Using operators (mimics command line)
    await Command.Run("ProcssingStep1.exe") < new FileInfo("input.txt")
        | Command.Run("processingStep2.exe") > new FileInfo("output.text");
    
    // Using PipeToAsync for collections
    var outputLines = new List<string>();
    await command.StandardOutput.PipeToAsync(outputLines);
  4. Install MedallionShell via NuGet

    master

    MedallionShell is available as a NuGet package. You can install the standard version or the strong-named version depending on your requirements.

    • Standard: MedallionShell
    • Strong-named: MedallionShell.StrongName
    # Use the NuGet package manager to install
    # dotnet add package MedallionShell
  5. Stop or signal a command

    master

    To terminate a running process, use the Kill() method for an immediate stop. For a more graceful shutdown, use TrySignalAsync to send specific signals. CommandSignal.ControlC is a cross-platform signal, while other signals may be OS-specific.

    var command = Command.Run("long-running-task");
    
    // Immediate termination
    command.Kill();
    
    // Graceful shutdown via signal
    await command.TrySignalAsync(CommandSignal.ControlC);
  6. Run a command with Command.Run

    master

    The Command class is the primary entry point for executing processes. Use Command.Run to start a new process with an executable and its arguments. You can wait for the command to finish synchronously using .Wait(), access the result via the .Result property, or await it asynchronously using the .Task property.

    // Create and run a command
    var command = Command.Run("git", "commit", "-m", "critical bugfix");
    
    // Wait for it to finish
    command.Wait();
    
    // Or await it asynchronously
    var result = await command.Task;
    
    // Inspect the result
    if (!result.Success)
    {
        Console.Error.WriteLine($"command failed with exit code {result.ExitCode}: {result.StandardError}");
    }
  7. Configure Command options

    master

    When running a command, you can provide an options callback to configure the process behavior. Supported options include:

    OptionDescriptionDefault
    ThrowOnErrorIf true, throws an exception if the process returns a non-zero exit codefalse
    WorkingDirectorySets the initial working directoryEnvironment.CurrentDirectory
    CancellationTokenSpecifies a CancellationToken which will kill the process if canceledCancellationToken.None
    TimeoutSpecifies a time period after which the process will be killedTimeout.Infinite
    StartInfoSpecifies arbitrary additional configuration of the ProcessStartInfo object
    DisposeOnExitIf true, the underlying Process object is disposed when the process exitstrue
    EnvironmentVariable(s)Specifies environment variable overridesEnvironment.GetEnvironmentVariables()
    EncodingSpecifies an Encoding to be used on all standard IO streamsConsole.OutputEncoding/Console.InputEncoding
    CommandSpecifies arbitrary additional configuration of the Command object
    Command.Run("foo.exe", new[] { "arg1" }, options => options.ThrowOnError().WorkingDirectory("C:\temp"));