using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.Core; namespace Tango.Core.Components { public class CmdCommand : ExtendedObject { public enum OutEncoding { Default, Unicode, } public enum ExitStrategies { WaitForExit, StandardOutput, } public class CmdCommandResult { public String StandardOutput { get; set; } public String StandardError { get; set; } public int ExitCode { get; set; } } private Process _process; public String Arguments { get; set; } public TimeSpan Timeout { get; set; } public String WorkingDir { get; set; } public OutEncoding OutputEncoding { get; set; } public ExitStrategies ExitStrategy { get; set; } public CmdCommand(String processName, String arguments) { Timeout = TimeSpan.FromSeconds(5); _process = new Process(); _process.StartInfo.CreateNoWindow = true; _process.StartInfo.FileName = processName; _process.StartInfo.UseShellExecute = false; _process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; _process.StartInfo.RedirectStandardError = true; _process.StartInfo.RedirectStandardOutput = true; _process.StartInfo.Arguments = arguments; _process.StartInfo.Verb = "runas"; if (WorkingDir != null) { _process.StartInfo.WorkingDirectory = WorkingDir; } Arguments = arguments; } public Task Run() { return Task.Factory.StartNew(() => { CmdCommandResult result = new CmdCommandResult(); LogManager.Log($"Starting process {_process.StartInfo.FileName} with arguments {Arguments}..."); _process.Start(); if (ExitStrategy == ExitStrategies.WaitForExit) { _process.WaitForExit((int)Timeout.TotalMilliseconds); } if (_process.HasExited || ExitStrategy == ExitStrategies.StandardOutput) { String output = _process.StandardOutput.ReadToEnd(); String error = _process.StandardError.ReadToEnd(); if (OutputEncoding == OutEncoding.Unicode) { byte[] data = Encoding.Default.GetBytes(output); output = Encoding.Unicode.GetString(data); data = Encoding.Default.GetBytes(error); error = Encoding.Unicode.GetString(data); } LogManager.Log($"Process exited with exit code {_process.ExitCode}."); LogManager.Log($"Process Standard Output:\n{output}"); LogManager.Log($"Process Standard Error:\n{error}"); if (_process.ExitCode != 0) { throw new IOException($"The process {_process.StartInfo.FileName} has exited with the code {_process.ExitCode}.\n{error}"); } result.StandardOutput = output; result.StandardError = error; result.ExitCode = _process.ExitCode; return result; } else { throw new TimeoutException($"The process {_process.StartInfo.FileName} has not exited within the given timeout of {Timeout.TotalSeconds} seconds."); } }); } } }