execute shell from c#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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