Last active
March 23, 2023 21:14
-
-
Save TorstenC/08f7cb52f20a041d2f6325bc61e2b0ae to your computer and use it in GitHub Desktop.
This class externalizes boiler plate code to run an external process with catching StandardOutput and StandardError.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> This class externalizes boiler plate code to run an external process | |
/// with catching StandardOutput and StandardError. </summary> | |
public class Processor | |
{ | |
public ProcessStartInfo StartInfo { get; set; } | |
public Exception? Exception { get; set; } | |
public Processor(string pathToExe, params string[] arguments) : this() | |
{ | |
StartInfo.FileName = pathToExe; | |
if (1 == arguments.Length) StartInfo.Arguments = arguments[0]; | |
else | |
foreach (var argument in arguments) | |
StartInfo.ArgumentList.Add(argument); | |
} | |
/// <summary> Instructs the Process component to wait the specified number of milliseconds for | |
/// the associated process to exit. </summary> | |
/// <param name="milliseconds">The amount of time, in milliseconds, to wait for the associated process to exit. | |
/// A value of 0 specifies an immediate return, and a value of -1 specifies an infinite wait.</param> | |
/// <returns><see cref="true"/> if the associated process has exited; otherwise, <see cref="false"/>.</returns> | |
public bool ExecuteWaitExit( Action<string>? line = null, int milliseconds = 0) | |
{ | |
Exception = null; | |
var proc = new Process() { StartInfo = StartInfo }; | |
if (proc is null) { | |
Exception = new Exception(); | |
return false; | |
}; | |
if (!proc.Start()) { | |
Exception = new Exception(); | |
return false; | |
}; | |
if (proc is null) { | |
Exception = new Exception(); | |
return false; | |
}; | |
if (line is not null) | |
{ | |
using (var stream = new MemoryStream()) | |
using (var writer = new StreamWriter(stream) as TextWriter) | |
using (var reader = new StreamReader(stream) as TextReader) | |
{ | |
((StreamWriter)writer).AutoFlush = true; | |
while (!proc.StandardOutput?.EndOfStream ?? false) | |
{ | |
var std = proc.StandardOutput?.ReadToEnd() ?? ""; | |
writer.Write('⓪' + std); | |
} | |
if (!proc.StandardError?.EndOfStream ?? false) | |
{ | |
var err = proc.StandardError?.ReadToEnd() ?? ""; | |
writer.Write('①' + err); | |
} | |
writer.WriteLine(); | |
stream.Position = 0; | |
while (reader.Peek() > -1) | |
line(reader.ReadLine() ?? ""); | |
} | |
} | |
if (proc.WaitForExit(milliseconds)) return true; | |
Exception = new Exception(); | |
return false; | |
} | |
private Processor() | |
{ | |
StartInfo = new ProcessStartInfo() | |
{ | |
UseShellExecute = false, | |
RedirectStandardOutput = true, | |
RedirectStandardError = true, | |
CreateNoWindow = true, | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The instruction
writer.WriteLine()
afterstream.Position = 0
is the crucial one!If an output does not end with a newline character, a
ReadLine()
method would block and wait for more input.