Exec 2.22.0
See the version list below for details.
dotnet add package Exec --version 2.22.0
NuGet\Install-Package Exec -Version 2.22.0
<PackageReference Include="Exec" Version="2.22.0" />
<PackageVersion Include="Exec" Version="2.22.0" />
<PackageReference Include="Exec" />
paket add Exec --version 2.22.0
#r "nuget: Exec, 2.22.0"
#:package Exec@2.22.0
#addin nuget:?package=Exec&version=2.22.0
#tool nuget:?package=Exec&version=2.22.0
A .NET library for executing subprocess commands
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): ReturnsExecResultwithWasCancelled = true - CancellationToken: Throws
OperationCanceledException(orTaskCanceledException)
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
timeoutcommand: The Windowstimeout.execommand doesn't work because it requires interactive input and fails with redirected stdin. Useping 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
| Product | Versions 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. |
-
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 |