예제 #1
0
        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));
 }