public static ICommandSpec AssignArgs(this ICommandSpec command, CommandArguments args, bool defineSpecName = true) { var propIndex = command.GetType().GetPublicProperties(true, true).ToDictionary(x => x.Name.ToLower()); foreach (var arg in args) { if (propIndex.TryGetValue(arg.Name.ToLower(), out PropertyInfo prop)) { var typedVal = Parsers.Convert(prop.PropertyType, arg.Value); prop.SetValue(command, typedVal); } } if (defineSpecName) { var specNameProp = nameof(ICommandSpec.SpecName).ToLower(); var argHash = string.Join(",", args.Select(a => $"{a.Name}:={a.Value}")).GetHashCode(); propIndex[specNameProp].SetValue(command, $"{command.CommandName}/{argHash}"); } return(command); }
/// <summary> /// Executes the <see cref="Command"/> command and redirects the output to this dialog form instance. /// </summary> private void ExecuteCommand() { string RemoveSensitiveInformation(string value) { if (value != null) { foreach (var commandArgument in CommandArguments) { if (commandArgument.ArgumentValue == null) { continue; } value = value.Replace(commandArgument.ArgumentValue, commandArgument.HiddenArgumentValue); } } return(value); } while (NextCommand) { try { var commandEcho = Path.Combine(CommandPath, Command); var arguments = string.Join(" ", CommandArguments.Select(f => f.ToStringHidden())); if (arguments != string.Empty) { arguments = " " + arguments; } Text = $@"Command output [{Command + arguments}]"; commandEcho = "> " + commandEcho + arguments + Environment.NewLine; tbProcessOutput.AppendText(commandEcho); arguments = string.Join(" ", CommandArguments.Select(f => f.ToString())); // create a process.. Process process = new Process { StartInfo = { FileName = Command, Arguments = arguments, UseShellExecute = false, CreateNoWindow = true, WorkingDirectory = WorkingDirectory, RedirectStandardOutput = true, RedirectStandardError = true } }; // subscribe to the process events with anonymous event handlers.. process.OutputDataReceived += (sender, e) => { // append new line endings to the each output string.. if (!string.IsNullOrEmpty(e.Data)) { // invocation is required (another process).. Invoke(new MethodInvoker(delegate { tbProcessOutput.AppendText( RemoveSensitiveInformation(e.Data) + Environment.NewLine); })); } }; process.ErrorDataReceived += (sender, e) => { // append new line endings to the each output string.. if (!String.IsNullOrEmpty(e.Data)) { // invocation is required (another process).. Invoke(new MethodInvoker(delegate { tbProcessOutput.AppendText( RemoveSensitiveInformation(e.Data) + Environment.NewLine); })); } }; // start the process after "hefty" initialization.. process.Start(); // asynchronously read the standard output of the spawned process. // This raises OutputDataReceived events for each line of output. process.BeginOutputReadLine(); process.BeginErrorReadLine(); // wait for the process to exit while "pumping" the software to be "responsive".. while (!process.HasExited) { Application.DoEvents(); Thread.Sleep(100); if (KillCurrentProcess) { KillCurrentProcess = false; process.Kill(); } } using (process) { CommandResult = process.ExitCode; } Application.DoEvents(); } catch (Exception ex) { tbProcessOutput.AppendText($"> Command execution failed with an exception '{ex.Message}'"); } tbProcessOutput.AppendText(Environment.NewLine); } btClose.Enabled = true; }