using System; using System.ComponentModel; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; namespace StellaOps.Interop; internal sealed class ToolProcessRunner : IToolProcessRunner { public async Task RunAsync( string tool, string toolPath, string args, string workingDirectory, CancellationToken ct = default) { var startInfo = new ProcessStartInfo { FileName = toolPath, Arguments = args, WorkingDirectory = workingDirectory, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; try { using var process = Process.Start(startInfo); if (process is null) { return ToolResult.Failed($"Failed to start tool: {tool}"); } var stdOutTask = process.StandardOutput.ReadToEndAsync(ct); var stdErrTask = process.StandardError.ReadToEndAsync(ct); await process.WaitForExitAsync(ct).ConfigureAwait(false); var stdout = await stdOutTask.ConfigureAwait(false); var stderr = await stdErrTask.ConfigureAwait(false); return process.ExitCode == 0 ? ToolResult.Ok(stdout, stderr, process.ExitCode) : ToolResult.Failed(stderr, stdout, process.ExitCode); } catch (Exception ex) when (ex is InvalidOperationException or Win32Exception) { return ToolResult.Failed(ex.Message); } } }