using System.Diagnostics; using System.Text; namespace BuildTool.Publishing; public sealed class ProcessResult { public required int ExitCode { get; init; } public required string StandardOutput { get; init; } public required string StandardError { get; init; } public bool Success => ExitCode == 0; } public static class ProcessRunner { /// /// Runs a command with output captured (for parsing results). /// public static ProcessResult RunCaptured(string fileName, string arguments, string? workingDirectory = null) { var stdout = new StringBuilder(); var stderr = new StringBuilder(); var psi = new ProcessStartInfo { FileName = fileName, Arguments = arguments, WorkingDirectory = workingDirectory ?? Directory.GetCurrentDirectory(), RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using var process = Process.Start(psi); if (process is null) { return new ProcessResult { ExitCode = -1, StandardOutput = "", StandardError = $"Failed to start process: {fileName}" }; } process.OutputDataReceived += (_, e) => { if (e.Data is not null) { stdout.AppendLine(e.Data); } }; process.ErrorDataReceived += (_, e) => { if (e.Data is not null) { stderr.AppendLine(e.Data); } }; process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.WaitForExit(); return new ProcessResult { ExitCode = process.ExitCode, StandardOutput = stdout.ToString(), StandardError = stderr.ToString() }; } /// /// Runs a command with output passed through to the console (for build commands in non-interactive mode). /// public static int RunPassthrough(string fileName, string arguments, string? workingDirectory = null) { var psi = new ProcessStartInfo { FileName = fileName, Arguments = arguments, WorkingDirectory = workingDirectory ?? Directory.GetCurrentDirectory(), UseShellExecute = false }; using var process = Process.Start(psi); if (process is null) { return -1; } process.WaitForExit(); return process.ExitCode; } }