Skip to content

Instantly share code, notes, and snippets.

@TorstenC
Last active March 23, 2023 21:14
Show Gist options
  • Save TorstenC/08f7cb52f20a041d2f6325bc61e2b0ae to your computer and use it in GitHub Desktop.
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.
/// <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,
};
}
}
@TorstenC
Copy link
Author

The instruction writer.WriteLine() after stream.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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment