public static RunProcessResult RunProcessSync(RunProcessParameters input, RunProcessOptions options) { using (var process = new Process()) { process.StartInfo.UseShellExecute = false; process.StartInfo.Arguments = string.Join(" ", input.Arguments.Select(x => x.Name + " " + x.Value).ToArray()); process.StartInfo.FileName = input.FileName; process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; process.StartInfo.CreateNoWindow = true; process.StartInfo.RedirectStandardError = true; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardInput = options.RedirectStandardInput; var stdoutSb = new StringBuilder(); var stderrSb = new StringBuilder(); using (var outputWaitHandle = new AutoResetEvent(false)) using (var errorWaitHandle = new AutoResetEvent(false)) { void ProcessOnOutputDataReceived(object sender, DataReceivedEventArgs e) { try { if (e.Data == null) { outputWaitHandle.Set(); } else { stdoutSb.AppendLine(e.Data); } } catch (Exception exception) { Trace.TraceError($"Error while executing process {input.FileName} and handling output: {exception}"); } } void ProcessOnErrorDataReceived(object sender, DataReceivedEventArgs e) { try { if (e.Data == null) { errorWaitHandle.Set(); } else { stderrSb.AppendLine(e.Data); } } catch (Exception exception) { Trace.TraceError($"Error while executing process {input.FileName} and handling error output: {exception}"); } } try { process.OutputDataReceived += ProcessOnOutputDataReceived; process.ErrorDataReceived += ProcessOnErrorDataReceived; // Start the process. All event handlers etc. are now registered process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); // convert timeout seconds to milliseconds var timeoutMS = options.TimeoutSeconds * 1000; // Also wait events to be done if (process.WaitForExit(timeoutMS) && outputWaitHandle.WaitOne(timeoutMS) && errorWaitHandle.WaitOne(timeoutMS)) { if (process.HasExited) { // Exited - return object / throw error if (process.ExitCode != 0 && options.ThrowExceptionOnErrorResponse == true) { throw new ApplicationException("External process execution failed with returncode: " + process.ExitCode + " and output: " + Environment.NewLine + stderrSb.ToString()); } return(new RunProcessResult() { ExitCode = process.ExitCode, Output = stdoutSb.ToString(), StdErr = stderrSb.ToString() }); } else { // Timeout & process is runnig if (options.KillProcessAfterTimeout) { process.Kill(); } throw new TimeoutException($"External process <{process.Id}> execution timed out after {options.TimeoutSeconds} seconds. (1)"); } } else { // Timeout & process is runnimg if (process.HasExited == false && options.KillProcessAfterTimeout == true) { process.Kill(); } throw new TimeoutException($"External process <{process.Id}> execution timed out after {options.TimeoutSeconds} seconds. (2)"); } } finally { process.OutputDataReceived -= ProcessOnOutputDataReceived; process.ErrorDataReceived -= ProcessOnErrorDataReceived; } } } }
/// <summary> /// Starts the process and waits results. /// </summary> /// <param name="input">Process data</param> /// <param name="options">Run options</param> /// <returns>{RunProcessResult}</returns> public static RunProcessResult RunProcess([PropertyTab] RunProcessParameters input, [PropertyTab] RunProcessOptions options) { return(Frends.Community.ExecuteProcess.RunProcess.RunProcessSync(input, options)); }