Exec 2.14.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Exec --version 2.14.0
                    
NuGet\Install-Package Exec -Version 2.14.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="Exec" Version="2.14.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Exec" Version="2.14.0" />
                    
Directory.Packages.props
<PackageReference Include="Exec" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Exec --version 2.14.0
                    
#r "nuget: Exec, 2.14.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.
#:package Exec@2.14.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Exec&version=2.14.0
                    
Install as a Cake Addin
#tool nuget:?package=Exec&version=2.14.0
                    
Install as a Cake Tool

A .NET library for executing subprocess commands

master NuGet

Installation

Install from NuGet:

dotnet add package Exec

This library supports .NET 5 and later versions.

Usage

Basic usage

The simplest way to execute a command:

var result = await Exec.RunAsync("echo hello");
Assert.Contains("hello", result.Output);

That's it! The library provides static methods on the Exec class with the following APIs:

Task<ExecResult> RunAsync(string command, CancellationToken cancellationToken = default)

Task<ExecResult> RunAsync(string command, ExecOption option, CancellationToken cancellationToken = default)

Configuration

Use ExecOption to customize behavior beyond the defaults:

Property Description Default
Shell The shell application used to execute the command. cmd.exe on Windows, /bin/bash on Linux and macOS.
ShellParameter Shell parameters for executing the script file. /q /c on Windows, empty string on Linux and macOS.
ShellExtension Script file extension. .bat on Windows, .sh on Linux and macOS.
TempFileLocation Directory where temporary script files are created. System temp directory.
Timeout Maximum execution time for the command. Zero (no timeout).
OutputDataReceivedHandler Handler for each line of standard output. Only called when IsStreamed=true. Output is discarded.
ErrorDataReceivedHandler Handler for each line of standard error. Only called when IsStreamed=true. Errors are discarded.
OnExitedHandler Handler called when the process exits. No action.
OnCancelledHandler Handler called when the process is cancelled. No action.
IsStreamed Enable asynchronous streaming of output/error data. false

Result

ExecResult provides the following information:

Property Description
Output Combined standard output and standard error when IsStreamed=false. Empty when IsStreamed=true.
ExitCode The process exit code.
ExitTime The time when the process exited.
WasCancelled true if the process was cancelled due to timeout or cancellation token; otherwise false.

Cancellation behavior

The library handles cancellation differently based on the source:

  • Timeout (via ExecOption.Timeout): Returns ExecResult with WasCancelled = true
  • CancellationToken: Throws OperationCanceledException (or TaskCanceledException)

This allows timeout scenarios to be handled gracefully while external cancellations propagate as exceptions.

Advanced usage

Execute PowerShell commands

var option = new ExecOption
{
    Shell = "pwsh",
    ShellParameter = "",
    ShellExtension = ".ps1"
};

var command = @"function Test-Add {
    [CmdletBinding()]
    param (
        [int]$Val1,
        [int]$Val2
    )

    Write-Output $($Val1 + $Val2)
}

Test-Add 10 12";

var result = await Exec.RunAsync(command, option);
Assert.Equal(0, result.ExitCode);
Assert.Contains("22", result.Output);

Execute commands with timeout

When using a timeout, the command returns a result with WasCancelled = true:

var option = new ExecOption
{
    Timeout = TimeSpan.FromSeconds(3)
};

// Note: On Windows, use 'ping' instead of 'timeout' because timeout.exe doesn't work with redirected stdin
var result = await Exec.RunAsync("ping 127.0.0.1 -n 60", option);

// Process was terminated due to timeout
Assert.True(result.WasCancelled);
Assert.NotEqual(0, result.ExitCode);

Stream stdout and stderr asynchronously

var output = new StringBuilder();
var option = new ExecOption
{
    IsStreamed = true,
    OutputDataReceivedHandler = async (line) =>
    {
        output.AppendLine(line);
        await Task.CompletedTask;
    }
};

var result = await Exec.RunAsync(@"echo hello
echo hello2
echo hello3", option);

Assert.Equal(0, result.ExitCode);
Assert.Empty(result.Output); // Output is empty in streaming mode

var capturedOutput = output.ToString();
Assert.Contains("hello", capturedOutput);
Assert.Contains("hello2", capturedOutput);
Assert.Contains("hello3", capturedOutput);

Use cancellation tokens

When using a cancellation token, the operation throws OperationCanceledException:

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));

try
{
    var result = await Exec.RunAsync("long-running-command", cts.Token);
}
catch (OperationCanceledException)
{
    // Command was cancelled via the cancellation token
}

Known limitations

  • Windows timeout command: The Windows timeout.exe command doesn't work because it requires interactive input and fails with redirected stdin. Use ping 127.0.0.1 -n <seconds> as an alternative for delays.

Versioning

This project uses automated semantic versioning. The major version is defined in the VERSION file, and the minor version is automatically incremented on each release. See VERSIONING.md for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 is compatible.  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 is compatible.  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 is compatible.  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.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net5.0

    • No dependencies.
  • net6.0

    • No dependencies.
  • net7.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.24.0 69 1/7/2026
2.23.0 34 1/7/2026
2.22.0 33 1/7/2026
2.21.0 32 1/7/2026
2.17.0 35 1/7/2026
2.14.0 34 1/7/2026
2.0.0 438 12/8/2025
1.3.0 158 12/4/2025
1.2.0 470 11/24/2023
1.1.0 175 10/15/2023
1.0.0 187 10/12/2023
0.9.2 142 10/12/2023
0.9.1 136 10/11/2023
0.9.0 137 10/11/2023
0.1.0-alpha 130 10/10/2023
0.0.1-alpha 117 10/10/2023