Intro
Many times we may need to execute a command to obtain an output. The typical one we encountered was that we used FFMpeg to implement a series of operations such as encoding and compression of the video, and so on. At that time, we used the FFMpegCore class library. The implementation principle of this class library is to start another process, start ffmpeg, pass the corresponding processing parameters, and obtain the processing progress based on the process output.
For easy use, two help classes are implemented to easily obtain the output of the process, namely ProcessExecutor and CommandRunner. The former is more flexible and can add its own additional event subscription processing through events. The latter is a simplified version, mainly to only obtain output. The implementation principles of the two are roughly the same. Start a Process and listen to its output events to obtain output.
ProcessExecutor
Using the example, this example is an example of getting the path to save the nuget package:
using var executor = new ProcessExecutor("dotnet", "nuget locals global-packages -l"); var folder = ; += (sender, str) => { if(str is null) return; (str); if(("global-packages:")) { folder = ("global-packages:".Length).Trim(); } }; (); (folder);
ProcessExecutor
The implementation code is as follows:
public class ProcessExecutor : IDisposable { public event EventHandler<int> OnExited; public event EventHandler<string> OnOutputDataReceived; public event EventHandler<string> OnErrorDataReceived; protected readonly Process _process; protected bool _started; public ProcessExecutor(string exePath) : this(new ProcessStartInfo(exePath)) { } public ProcessExecutor(string exePath, string arguments) : this(new ProcessStartInfo(exePath, arguments)) { } public ProcessExecutor(ProcessStartInfo startInfo) { _process = new Process() { StartInfo = startInfo, EnableRaisingEvents = true, }; _process. = false; _process. = true; _process. = true; _process. = true; _process. = true; } protected virtual void InitializeEvents() { _process.OutputDataReceived += (sender, args) => { if ( != null) { OnOutputDataReceived?.Invoke(sender, ); } }; _process.ErrorDataReceived += (sender, args) => { if ( != null) { OnErrorDataReceived?.Invoke(sender, ); } }; _process.Exited += (sender, args) => { if (sender is Process process) { OnExited?.Invoke(sender, ); } else { OnExited?.Invoke(sender, _process.ExitCode); } }; } protected virtual void Start() { if (_started) { return; } _started = true; _process.Start(); _process.BeginOutputReadLine(); _process.BeginErrorReadLine(); _process.WaitForExit(); } public async virtual Task SendInput(string input) { try { await _process.(input!); } catch (Exception e) { OnErrorDataReceived?.Invoke(_process, ()); } } public virtual int Execute() { InitializeEvents(); Start(); return _process.ExitCode; } public virtual async Task<int> ExecuteAsync() { InitializeEvents(); return await (() => { Start(); return _process.ExitCode; }).ConfigureAwait(false); } public virtual void Dispose() { _process.Dispose(); OnExited = null; OnOutputDataReceived = null; OnErrorDataReceived = null; } }
CommandExecutor
The above method is more flexible but a bit complicated, so the following version is available
Example of usage:
[Fact] public void HostNameTest() { if (!()) { return; } var result = ("hostname"); var hostName = (); (hostName, ()); (0, ); }
Implement source code:
public static class CommandRunner { public static int Execute(string commandPath, string arguments = null, string workingDirectory = null) { using var process = new Process() { StartInfo = new ProcessStartInfo(commandPath, arguments ?? ) { UseShellExecute = false, CreateNoWindow = true, WorkingDirectory = workingDirectory ?? } }; (); (); return ; } public static CommandResult ExecuteAndCapture(string commandPath, string arguments = null, string workingDirectory = null) { using var process = new Process() { StartInfo = new ProcessStartInfo(commandPath, arguments ?? ) { UseShellExecute = false, CreateNoWindow = true, RedirectStandardOutput = true, RedirectStandardError = true, WorkingDirectory = workingDirectory ?? } }; (); var standardOut = (); var standardError = (); (); return new CommandResult(, standardOut, standardError); } } public sealed class CommandResult { public CommandResult(int exitCode, string standardOut, string standardError) { ExitCode = exitCode; StandardOut = standardOut; StandardError = standardError; } public string StandardOut { get; } public string StandardError { get; } public int ExitCode { get; } }
More
If you only need to use the command to obtain whether the execution is successful, you can use it. Only the output and whether it is successful can you use the method. If you want to add event subscriptions, you can use ProcessExecutor.
Reference
/rosenbjerg/FFMpegCore
/WeihanLi//blob/dev/src//Helpers/
/WeihanLi//blob/dev/test//HelpersTest/
/WeihanLi//blob/dev/test//HelpersTest/
The above is the detailed content of how to use C# to capture process output. For more information about C# to capture process output, please pay attention to my other related articles!