You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
2.8 KiB
98 lines
2.8 KiB
using System.Diagnostics; |
|
using System.Text; |
|
|
|
namespace StabilityMatrix.Core.Processes; |
|
|
|
/// <summary> |
|
/// Process supporting parsing of ANSI escape sequences |
|
/// </summary> |
|
public class AnsiProcess : Process |
|
{ |
|
private AsyncStreamReader? stdoutReader; |
|
private AsyncStreamReader? stderrReader; |
|
|
|
public AnsiProcess(ProcessStartInfo startInfo) |
|
{ |
|
StartInfo = startInfo; |
|
EnableRaisingEvents = false; |
|
|
|
StartInfo.UseShellExecute = false; |
|
StartInfo.CreateNoWindow = true; |
|
StartInfo.RedirectStandardOutput = true; |
|
StartInfo.RedirectStandardInput = true; |
|
StartInfo.RedirectStandardError = true; |
|
|
|
// Need this to parse ANSI escape sequences correctly |
|
StartInfo.StandardOutputEncoding = new UTF8Encoding(false); |
|
StartInfo.StandardErrorEncoding = new UTF8Encoding(false); |
|
StartInfo.StandardInputEncoding = new UTF8Encoding(false); |
|
} |
|
|
|
/// <summary> |
|
/// Start asynchronous reading of stdout and stderr |
|
/// </summary> |
|
/// <param name="callback">Called on each new line</param> |
|
public void BeginAnsiRead(Action<ProcessOutput> callback) |
|
{ |
|
var stdoutStream = StandardOutput.BaseStream; |
|
stdoutReader = new AsyncStreamReader( |
|
stdoutStream, |
|
s => |
|
{ |
|
if (s == null) |
|
return; |
|
callback(ProcessOutput.FromStdOutLine(s)); |
|
}, |
|
StandardOutput.CurrentEncoding |
|
); |
|
|
|
var stderrStream = StandardError.BaseStream; |
|
stderrReader = new AsyncStreamReader( |
|
stderrStream, |
|
s => |
|
{ |
|
if (s == null) |
|
return; |
|
callback(ProcessOutput.FromStdErrLine(s)); |
|
}, |
|
StandardError.CurrentEncoding |
|
); |
|
|
|
stdoutReader.BeginReadLine(); |
|
stderrReader.BeginReadLine(); |
|
} |
|
|
|
/// <summary> |
|
/// Waits for output readers to finish |
|
/// </summary> |
|
public async Task WaitUntilOutputEOF(CancellationToken ct = default) |
|
{ |
|
if (stdoutReader is not null) |
|
{ |
|
await stdoutReader.EOF.WaitAsync(ct).ConfigureAwait(false); |
|
} |
|
if (stderrReader is not null) |
|
{ |
|
await stderrReader.EOF.WaitAsync(ct).ConfigureAwait(false); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Cancels stream readers, no effect if already cancelled |
|
/// </summary> |
|
public void CancelStreamReaders() |
|
{ |
|
stdoutReader?.CancelOperation(); |
|
stderrReader?.CancelOperation(); |
|
} |
|
|
|
protected override void Dispose(bool disposing) |
|
{ |
|
CancelStreamReaders(); |
|
stdoutReader?.Dispose(); |
|
stdoutReader = null; |
|
stderrReader?.Dispose(); |
|
stderrReader = null; |
|
base.Dispose(disposing); |
|
} |
|
}
|
|
|