using System.Diagnostics; using Core.Events; using Core.Exceptions; namespace Generator.Infrastructure; public class CommandExecutor { private readonly Queue _commands; private string _invite; private DisplayEmitter _emitter; public CommandExecutor(string invite, DisplayEmitter emitter) { _commands = new Queue(); _invite = invite; _emitter = emitter; } /// /// Runs a single asynchronous command /// /// Command to run /// When the command hasn't been terminated successfully public async Task RunAsync(string command) { await Task.Run(() => { using var process = new Process(); process.StartInfo = new ProcessStartInfo { FileName = _invite, Arguments = $"{command}", RedirectStandardOutput = true, RedirectStandardError = true, WindowStyle = ProcessWindowStyle.Normal }; process.Start(); ReadOutput(process); ReadError(process); process.WaitForExit(); if(process.ExitCode == 1) throw new CommandExecutionException($"The following task has failed : \n '{command}'"); }); } private void ReadError(Process process) { Task.Run(async () => { using var output = process.StandardError; while (!output.EndOfStream) { var line = await output.ReadLineAsync(); _emitter.Warn(this, line.ToString()); } }); } private void ReadOutput(Process process) { Task.Run(async () => { using var output = process.StandardOutput; while (!output.EndOfStream) { var line = await output.ReadLineAsync(); _emitter.Say(this, line); } }); } /// /// Registers a command to execute later /// /// public void Register(string command) => _commands.Enqueue(command); /// /// Runs all previously registered command /// public async Task RunRegistered() { while (_commands.TryDequeue(out var c)) { await RunAsync(c); } } }