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;
}
}