Пример #1
0
        // ************************************************************************
        /// <summary>
        /// Only support existing exectuable (no association or dos command which have no executable like 'dir').
        /// But accept full path, partial path or no path where it will use regular system/user path.
        /// </summary>
        /// <param name="executablePath"></param>
        /// <param name="arguments"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        private ProcessWithOutputCaptureResult ExecuteInternal(string executablePath, string arguments, int timeout = Timeout.Infinite, ProcessWindowStyle processWindowStyle = ProcessWindowStyle.Hidden)
        {
            ProcessWithOutputCaptureResult processWithOutputCaptureResult = null;

            using (Process process = new Process())
            {
                process.StartInfo.FileName        = executablePath;
                process.StartInfo.Arguments       = arguments;
                process.StartInfo.UseShellExecute = false;

                process.StartInfo.WindowStyle = processWindowStyle;
                if (processWindowStyle == ProcessWindowStyle.Hidden)
                {
                    process.StartInfo.CreateNoWindow = true;
                }

                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError  = true;

                _outputWaitHandle = new AutoResetEvent(false);
                _errorWaitHandle  = new AutoResetEvent(false);
                try
                {
                    process.OutputDataReceived += ProcessOnOutputDataReceived;
                    process.ErrorDataReceived  += ProcessOnErrorDataReceived;

                    process.Start();

                    process.BeginOutputReadLine();
                    process.BeginErrorReadLine();

                    _sbOutput.AppendLine(process.StandardOutput.ReadToEnd());
                    _sbError.AppendLine(process.StandardError.ReadToEnd());

                    if (process.WaitForExit(timeout) && _outputWaitHandle.WaitOne(timeout) && _errorWaitHandle.WaitOne(timeout))
                    {
                        processWithOutputCaptureResult = ProcessWithOutputCaptureResult.CreateOne(process.ExitCode, _sbOutput.ToString(), _sbError.ToString());
                    }
                    else
                    {
                        processWithOutputCaptureResult = ProcessWithOutputCaptureResult.CreateExpiredOne();
                    }
                }
                finally
                {
                    process.OutputDataReceived -= ProcessOnOutputDataReceived;
                    process.ErrorDataReceived  -= ProcessOnOutputDataReceived;

                    _outputWaitHandle.Close();
                    _outputWaitHandle.Dispose();

                    _errorWaitHandle.Close();
                    _errorWaitHandle.Dispose();
                }
            }

            return(processWithOutputCaptureResult);
        }
Пример #2
0
        // ************************************************************************
        /// <summary>
        /// Only support existing exectuable (no association or dos command which have no executable like 'dir').
        /// But accept full path, partial path or no path where it will use regular system/user path.
        /// </summary>
        /// <param name="executablePath"></param>
        /// <param name="arguments"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        private ProcessWithOutputCaptureResult ExecuteInternal(string executablePath, string arguments, int timeout = Timeout.Infinite, ProcessWindowStyle processWindowStyle = ProcessWindowStyle.Hidden)
        {
            ProcessWithOutputCaptureResult processWithOutputCaptureResult = null;

            using (Process process = new Process())
            {
                process.StartInfo.FileName        = executablePath;
                process.StartInfo.Arguments       = arguments;
                process.StartInfo.UseShellExecute = false;                 // required to redirect output to appropriate (output or error) process stream

                process.StartInfo.WindowStyle = processWindowStyle;
                if (processWindowStyle == ProcessWindowStyle.Hidden)
                {
                    process.StartInfo.CreateNoWindow = true;
                }

                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError  = true;

                try
                {
                    process.Start();

                    bool hasSucceeded = process.WaitForExit(timeout);
                    processWithOutputCaptureResult = ProcessWithOutputCaptureResult.CreateOne(process.ExitCode, process.StandardOutput.ReadToEnd(), process.StandardError.ReadToEnd());
                    processWithOutputCaptureResult = ProcessWithOutputCaptureResult.CreateExpiredOne();

                    processWithOutputCaptureResult            = new ProcessWithOutputCaptureResult();
                    processWithOutputCaptureResult.ExitCode   = process.ExitCode;
                    processWithOutputCaptureResult.Output     = process.StandardOutput.ReadToEnd();
                    processWithOutputCaptureResult.Error      = process.StandardError.ReadToEnd();
                    processWithOutputCaptureResult.HasTimeout = !hasSucceeded;
                }
                catch (Exception ex)
                {
                    if (ex.HResult == -2147467259)
                    {
                        ProcessWithOutputCaptureResult.CreateOneWithException(new FileNotFoundException("File not found: " + executablePath, ex));
                    }
                    else
                    {
                        ProcessWithOutputCaptureResult.CreateOneWithException(ex);
                    }
                }
            }

            return(processWithOutputCaptureResult);
        }
Пример #3
0
        // ************************************************************************
        /// <summary>
        /// Only support existing exectuable (no association or dos command which have no executable like 'dir').
        /// But accept full path, partial path or no path where it will use regular system/user path.
        /// </summary>
        /// <param name="executablePath"></param>
        /// <param name="arguments"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        private ProcessWithOutputCaptureResult ExecuteInternal(string executablePath, string arguments, int timeout = Timeout.Infinite, ProcessWindowStyle processWindowStyle = ProcessWindowStyle.Hidden)
        {
            ProcessWithOutputCaptureResult processWithOutputCaptureResult = null;

            using (Process process = new Process())
            {
                process.StartInfo.FileName        = executablePath;
                process.StartInfo.Arguments       = arguments;
                process.StartInfo.UseShellExecute = false;                 // required to redirect output to appropriate (output or error) process stream

                process.StartInfo.WindowStyle = processWindowStyle;
                if (processWindowStyle == ProcessWindowStyle.Hidden)
                {
                    process.StartInfo.CreateNoWindow = true;
                }

                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError  = true;

                _outputWaitHandle = new AutoResetEvent(false);
                _errorWaitHandle  = new AutoResetEvent(false);
                try
                {
                    process.OutputDataReceived += ProcessOnOutputDataReceived;
                    process.ErrorDataReceived  += ProcessOnErrorDataReceived;

                    process.Start();

                    process.BeginOutputReadLine();
                    process.BeginErrorReadLine();

                    // See: ProcessStartInfo.RedirectStandardOutput Property:
                    //		https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(System.Diagnostics.ProcessStartInfo.RedirectStandardOutput);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5.2);k(DevLang-csharp)&rd=true
                    // All 4 next lines should only be called when not using asynchronous read (process.BeginOutputReadLine() and process.BeginErrorReadLine())
                    //_sbOutput.AppendLine(process.StandardOutput.ReadToEnd());
                    //_sbError.AppendLine(process.StandardError.ReadToEnd());
                    //_sbOutput.AppendLine(process.StandardOutput.ReadToEnd());
                    //_sbError.AppendLine(process.StandardError.ReadToEnd());

                    if (process.WaitForExit(timeout) && _outputWaitHandle.WaitOne(timeout) && _errorWaitHandle.WaitOne(timeout))
                    {
                        processWithOutputCaptureResult = ProcessWithOutputCaptureResult.CreateOne(process.ExitCode, _sbOutput.ToString(), _sbError.ToString());
                    }
                    else
                    {
                        processWithOutputCaptureResult = ProcessWithOutputCaptureResult.CreateExpiredOne();
                    }
                }
                catch (Exception ex)
                {
                    if (ex.HResult == -2147467259)
                    {
                        ProcessWithOutputCaptureResult.CreateOneWithException(new FileNotFoundException("File not found: " + executablePath, ex));
                    }
                    else
                    {
                        ProcessWithOutputCaptureResult.CreateOneWithException(ex);
                    }
                }
                finally
                {
                    process.CancelOutputRead();
                    process.CancelErrorRead();

                    process.OutputDataReceived -= ProcessOnOutputDataReceived;
                    process.ErrorDataReceived  -= ProcessOnOutputDataReceived;

                    _outputWaitHandle.Close();
                    _outputWaitHandle.Dispose();

                    _errorWaitHandle.Close();
                    _errorWaitHandle.Dispose();
                }
            }

            return(processWithOutputCaptureResult);
        }
        // ************************************************************************
        /// <summary>
        /// Only support existing exectuable (no association or dos command which have no executable like 'dir').
        /// But accept full path, partial path or no path where it will use regular system/user path.
        /// </summary>
        /// <param name="executablePath"></param>
        /// <param name="arguments"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        private ProcessWithOutputCaptureResult Execute(string executablePath, string arguments = null, int timeout = Timeout.Infinite)
        {
            ProcessWithOutputCaptureResult processWithOutputCaptureResult = null;

            using (Process process = new Process())
            {
                process.StartInfo.FileName        = executablePath;
                process.StartInfo.Arguments       = arguments;
                process.StartInfo.UseShellExecute = false;                 // required to redirect output to appropriate (output or error) process stream

                process.StartInfo.WindowStyle    = ProcessWindowStyle;
                process.StartInfo.CreateNoWindow = CreateWindow;

                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError  = true;

                _outputWaitHandle = new AutoResetEvent(false);
                _errorWaitHandle  = new AutoResetEvent(false);

                bool asyncReadStarted = false;

                try
                {
                    process.OutputDataReceived += ProcessOnOutputDataReceived;
                    process.ErrorDataReceived  += ProcessOnErrorDataReceived;

                    process.Start();

                    // Here there is a race condition. See: https://connect.microsoft.com/VisualStudio/feedback/details/3119134/race-condition-in-process-asynchronous-output-stream-read

                    process.BeginOutputReadLine();
                    process.BeginErrorReadLine();

                    asyncReadStarted = true;

                    // See: ProcessStartInfo.RedirectStandardOutput Property:
                    //		https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(System.Diagnostics.ProcessStartInfo.RedirectStandardOutput);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5.2);k(DevLang-csharp)&rd=true
                    // All 4 next lines should only be called when not using asynchronous read (process.BeginOutputReadLine() and process.BeginErrorReadLine())
                    //_sbOutput.AppendLine(process.StandardOutput.ReadToEnd());
                    //_sbError.AppendLine(process.StandardError.ReadToEnd());
                    //_sbOutput.AppendLine(process.StandardOutput.ReadToEnd());
                    //_sbError.AppendLine(process.StandardError.ReadToEnd());

                    var waitHandles = new WaitHandle[1 + (AdditionalConditionToStopWaitingProcess == null ? 0 : 1)];

                    waitHandles[0] = new ProcessWaitHandle(process);
                    if (AdditionalConditionToStopWaitingProcess != null)
                    {
                        waitHandles[1] = AdditionalConditionToStopWaitingProcess;
                    }

                    bool hasSucceded = false;
                    int  waitResult  = WaitHandle.WaitAny(waitHandles, timeout);
                    if (waitResult == 1)                     // The wait has been interrrupted by an external event
                    {
                        if (IsAdditionalConditionToStopWaitingProcessShouldAlsoKill)
                        {
                            process.Kill();
                        }
                    }
                    else if (waitResult == 0)                     // Process has completed normally, no timeout or external event
                    {
                        // Ensure internal process code has completed like ensure to wait until stdout et stderr had been fully completed
                        hasSucceded = process.WaitForExit(timeout);

                        if (_outputWaitHandle.WaitOne(timeout) && _errorWaitHandle.WaitOne(timeout))
                        {
                            processWithOutputCaptureResult          = new ProcessWithOutputCaptureResult();
                            processWithOutputCaptureResult.ExitCode = process.ExitCode;
                            processWithOutputCaptureResult.Output   = _sbOutput.ToString();
                            processWithOutputCaptureResult.Error    = _sbError.ToString();
                        }
                    }
                    else                     // Process timeout
                    {
                        processWithOutputCaptureResult            = new ProcessWithOutputCaptureResult();
                        processWithOutputCaptureResult.HasTimeout = true;
                    }
                }
                catch (Exception ex)
                {
                    if (ex.HResult == -2147467259)
                    {
                        processWithOutputCaptureResult           = new ProcessWithOutputCaptureResult();
                        processWithOutputCaptureResult.Exception = new FileNotFoundException("File not found: " + executablePath, ex);
                    }
                    else
                    {
                        processWithOutputCaptureResult           = new ProcessWithOutputCaptureResult();
                        processWithOutputCaptureResult.Exception = ex;
                    }
                }
                finally
                {
                    if (asyncReadStarted)
                    {
                        process.CancelOutputRead();
                        process.CancelErrorRead();
                    }

                    process.OutputDataReceived -= ProcessOnOutputDataReceived;
                    process.ErrorDataReceived  -= ProcessOnOutputDataReceived;

                    _outputWaitHandle.Close();
                    _outputWaitHandle.Dispose();

                    _errorWaitHandle.Close();
                    _errorWaitHandle.Dispose();
                }
            }

            return(processWithOutputCaptureResult);
        }