CliWrap is an open-source library for .NET that simplifies the execution and management of external processes in C# applications.
In other words, it is basically a hyper-boosted replacement for Process.Start(...)
with all the process management options you can imagine.
CliWrap is designed to offer an intuitive interface that allows us to interact with the command line easily, for example, by managing command execution or capturing output.
Features of CliWrap,
- Fluent interface: Provides a modern and fluent API for working with external processes, improving code readability and maintainability.
- Command support: Allows for the execution of command line commands and scripts, with support for arguments and parameters.
- Output capture: Facilitates the capture and handling of standard output and error from processes, as well as standard input.
- Asynchronicity: Supports the asynchronous execution of commands, ideal for applications requiring non-blocking operations.
- Flexible configuration: Offers advanced options for process configuration, including input/output redirection and timeout settings.
Installing CliWrap
To use CliWrap in your .NET project, you need to add the corresponding package via NuGet. You can do this through the Package Manager Console in Visual Studio or by using the .NET CLI. Here’s the command to install CliWrap:
Install-Package CliWrap
Using CliWrap
Running a simple command
To run a simple command line command, you can use the Cli
class from CliWrap. Here’s a basic example that executes the echo
command:
var result = await Cli.Wrap("cmd")
.WithArguments(["echo", "Hello, CliWrap!"])
.ExecuteAsync();
Console.WriteLine($"Exit Code: {result.ExitCode}");
In this example:
Cli.Wrap("echo")
: Creates an instance ofCli
for theecho
command.WithArguments("Hello, CliWrap!")
: Sets the command arguments.ExecuteAsync()
: Executes the command asynchronously and waits for its completion.
Capturing output
To capture the standard and error output of a process, you can configure the output and error handlers. Here’s an example that captures the output and error of the ls
command:
var result = await Cli.Wrap("cmd")
.WithStandardOutputPipe(PipeTarget.ToDelegate(Console.WriteLine))
.WithStandardErrorPipe(PipeTarget.ToDelegate(Console.Error.WriteLine))
.ExecuteAsync();
Console.WriteLine($"Exit Code: {result.ExitCode}");
In this example:
WithStandardOutputPipe(PipeTarget.ToDelegate(Console.WriteLine))
: Redirects the standard output of the command to the delegate that writes to the console.WithStandardErrorPipe(PipeTarget.ToDelegate(Console.Error.WriteLine))
: Redirects the error output of the command to the delegate that writes to the error console.
Or, we can send it to a StringBuilder
to have the data in memory.
var stdOutBuffer = new StringBuilder();
var result = await Cli.Wrap("cmd")
.WithStandardOutputPipe(PipeTarget.ToDelegate(Console.WriteLine))
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(stdOutBuffer))
.ExecuteAsync();
Console.WriteLine($"Exit Code: {result.ExitCode}");
Handling Standard Input
CliWrap also allows sending data to the standard input of the process. We can have a process and send commands to it through standard input. Here’s an example from a string, although there are many other Pipes
we can use.
var result = await Cli.Wrap("cmd")
.WithStandardInputPipe(PipeSource.FromString("\ndir\n"))
.WithStandardOutputPipe(PipeTarget.ToDelegate(Console.WriteLine))
.ExecuteAsync();
Console.WriteLine($"Exit Code: {result.ExitCode}");
In this example:
WithStandardInputPipe(PipeSource.FromString(...)
: We use a string as a source of commands to send to the process. In this case, we simply send thedir
command to thecmd
process.
Additional Configuration
CliWrap allows for additional configuration to set timeouts, the working directory, and other process parameters. Here’s an example of how to set a timeout for the execution of a command:
using System;
using System.Threading.Tasks;
using CliWrap;
class Program
{
static async Task Main(string[] args)
{
var result = await Cli.Wrap("sleep")
.WithArguments("10")
.WithTimeout(TimeSpan.FromSeconds(5))
.ExecuteAsync();
Console.WriteLine($"Exit Code: {result.ExitCode}");
}
}
In this example:
WithTimeout(TimeSpan.FromSeconds(5))
: Sets a timeout of 5 seconds for thesleep
command.