Skip to content

Instantly share code, notes, and snippets.

@nekomimi-daimao
Created December 29, 2021 17:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nekomimi-daimao/e2f100092b1ca84c1cae8773754d866f to your computer and use it in GitHub Desktop.
Save nekomimi-daimao/e2f100092b1ca84c1cae8773754d866f to your computer and use it in GitHub Desktop.
execute shell from c#
using System.Diagnostics;
using System.Text;
namespace Nekomimi.Daimao
{
public static class ShellUtil
{
public static int TimeoutMinutes = 30;
public static async Task<ShellResult> Do(string command, string args, CancellationToken baseToken)
{
var startInfo =
string.IsNullOrEmpty(args)
? new ProcessStartInfo(command)
: new ProcessStartInfo(command, args);
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardInput = false;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
using (var process = Process.Start(startInfo))
using (var cancelSource = CancellationTokenSource.CreateLinkedTokenSource(baseToken))
{
try
{
if (process == null)
{
return ShellResult.None;
}
cancelSource.CancelAfter(TimeSpan.FromMinutes(TimeoutMinutes));
var token = cancelSource.Token;
var output = await process.StandardOutput.ReadToEndAsync();
var error = await process.StandardError.ReadToEndAsync();
await process.WaitForExitAsync(token);
return new ShellResult(process.ExitCode, output, error);
}
catch (Exception e)
{
var errorMessage = e?.Message ?? "Error";
return new ShellResult(-1, null, errorMessage);
}
}
}
public static Task<ShellResult> Do(string command)
{
return Do(command, string.Empty, CancellationToken.None);
}
public static Task<ShellResult> Do(string command, CancellationToken token)
{
return Do(command, string.Empty, token);
}
public static Task<ShellResult> Do(string command, string arg)
{
return Do(command, arg, CancellationToken.None);
}
public static Task<ShellResult> Do(string command, CancellationToken token, params string[] arg)
{
if (arg.Length == 0)
{
return Do(command, string.Empty, token);
}
var sb = new StringBuilder();
foreach (var s in arg)
{
sb.Append(s).Append(' ');
}
return Do(command, sb.ToString(), token);
}
public static Task<ShellResult> Do(string command, params string[] arg)
{
return Do(command, CancellationToken.None, arg);
}
[Serializable]
public struct ShellResult
{
public readonly int ExitCode;
public readonly string? Output;
public readonly string? Error;
public ShellResult(int exitCode, string? output, string? error)
{
ExitCode = exitCode;
Output = output;
Error = error;
}
public static ShellResult None => new ShellResult(-1, null, null);
public override string ToString()
{
return $"{nameof(ExitCode)}: {ExitCode}, {nameof(Output)}: {Output}, {nameof(Error)}: {Error}";
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment