wip
This commit is contained in:
commit
03ebf47b9f
33 changed files with 1657 additions and 0 deletions
90
src/core/Shellify.cs
Normal file
90
src/core/Shellify.cs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
internal static class Shellify
|
||||
{
|
||||
[Flags]
|
||||
private enum ShellSplitState
|
||||
{
|
||||
None = 0,
|
||||
InSingleQuote = 1 << 0,
|
||||
InDoubleQuote = 1 << 1,
|
||||
Escape = 1 << 2
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Splits a shell-escaped string into arguments, handling quotes and escapes.
|
||||
/// </summary>
|
||||
public static List<string> ShellSplit(string input)
|
||||
{
|
||||
var args = new List<string>();
|
||||
if (string.IsNullOrEmpty(input)) return args;
|
||||
var current = new System.Text.StringBuilder();
|
||||
var state = ShellSplitState.None;
|
||||
foreach (char c in input)
|
||||
{
|
||||
if (state.HasFlag(ShellSplitState.Escape))
|
||||
{
|
||||
current.Append(c);
|
||||
state &= ~ShellSplitState.Escape;
|
||||
}
|
||||
else if (c == '\\')
|
||||
{
|
||||
state |= ShellSplitState.Escape;
|
||||
}
|
||||
else if (c == '\'' && !state.HasFlag(ShellSplitState.InDoubleQuote))
|
||||
{
|
||||
state ^= ShellSplitState.InSingleQuote;
|
||||
}
|
||||
else if (c == '"' && !state.HasFlag(ShellSplitState.InSingleQuote))
|
||||
{
|
||||
state ^= ShellSplitState.InDoubleQuote;
|
||||
}
|
||||
else if (char.IsWhiteSpace(c) && !state.HasFlag(ShellSplitState.InSingleQuote) && !state.HasFlag(ShellSplitState.InDoubleQuote))
|
||||
{
|
||||
if (current.Length > 0)
|
||||
{
|
||||
args.Add(current.ToString());
|
||||
current.Clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
current.Append(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (current.Length > 0)
|
||||
args.Add(current.ToString());
|
||||
return args;
|
||||
}
|
||||
|
||||
public static TaskAwaiter<string> GetAwaiter(this string command)
|
||||
{
|
||||
return RunProcessAsync(command).GetAwaiter();
|
||||
}
|
||||
|
||||
private static async Task<string> RunProcessAsync(string command)
|
||||
{
|
||||
var strings = ShellSplit(command);
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = strings.First(),
|
||||
ArgumentList =
|
||||
{
|
||||
strings.Skip(1)
|
||||
},
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
};
|
||||
using var process = Process.Start(psi);
|
||||
string output = await process.StandardOutput.ReadToEndAsync();
|
||||
string error = await process.StandardError.ReadToEndAsync();
|
||||
await process.WaitForExitAsync();
|
||||
if (process.ExitCode != 0)
|
||||
throw new System.Exception($"Process exited with code {process.ExitCode}: {error}");
|
||||
return output;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue