public void Run() { DateTimeOffset lastOutput = DateTimeOffset.UtcNow; Exception thrownException = null; var gotOutput = new AutoResetEvent(false); if (Process.StartInfo.RedirectStandardError) { Process.ErrorDataReceived += (s, e) => { //if (e.Data != null) //{ // Logger.Trace("ErrorData \"" + (e.Data == null ? "'null'" : e.Data) + "\""); //} lastOutput = DateTimeOffset.UtcNow; gotOutput.Set(); if (e.Data != null) { var line = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(e.Data)); errors.Add(line.TrimEnd('\r', '\n')); Logger.Trace(line); } }; } if (Process.StartInfo.RedirectStandardOutput) { Process.OutputDataReceived += (s, e) => { lastOutput = DateTimeOffset.UtcNow; gotOutput.Set(); if (e.Data != null) { var line = Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(e.Data)); outputProcessor.LineReceived(line.TrimEnd('\r', '\n')); } else { outputProcessor.LineReceived(null); } }; } try { Logger.Trace($"Running '{Process.StartInfo.FileName} {Process.StartInfo.Arguments}'"); token.ThrowIfCancellationRequested(); Process.Start(); if (Process.StartInfo.RedirectStandardInput) { Input = new StreamWriter(Process.StandardInput.BaseStream, new UTF8Encoding(false)); } if (Process.StartInfo.RedirectStandardError) { Process.BeginErrorReadLine(); } if (Process.StartInfo.RedirectStandardOutput) { Process.BeginOutputReadLine(); } onStart?.Invoke(); if (Process.StartInfo.CreateNoWindow) { bool done = false; while (!done) { var exited = WaitForExit(500); if (exited) { // process is done and we haven't seen output, we're done done = !gotOutput.WaitOne(100); } else if (token.IsCancellationRequested || (taskName.Contains("git lfs") && lastOutput.AddMilliseconds(ApplicationConfiguration.DefaultGitTimeout) < DateTimeOffset.UtcNow)) // if we're exiting or we haven't had output for a while { Stop(true); token.ThrowIfCancellationRequested(); throw new ProcessException(-2, "Process timed out"); } } if (Process.ExitCode != 0 && errors.Count > 0) { thrownException = new ProcessException(Process.ExitCode, string.Join(Environment.NewLine, errors.ToArray())); } } } catch (Exception ex) { var errorCode = -42; if (ex is Win32Exception) { errorCode = ((Win32Exception)ex).NativeErrorCode; } StringBuilder sb = new StringBuilder(); sb.AppendLine($"Error code {errorCode}"); sb.AppendLine(ex.Message); if (Process.StartInfo.Arguments.Contains("-credential")) { sb.AppendLine($"'{Process.StartInfo.FileName} {taskName}'"); } else { sb.AppendLine($"'{Process.StartInfo.FileName} {Process.StartInfo.Arguments}'"); } if (errorCode == 2) { sb.AppendLine("The system cannot find the file specified."); } foreach (string env in Process.StartInfo.EnvironmentVariables.Keys) { sb.AppendFormat("{0}:{1}", env, Process.StartInfo.EnvironmentVariables[env]); sb.AppendLine(); } thrownException = new ProcessException(errorCode, sb.ToString(), ex); } if (thrownException != null || errors.Count > 0) { onError?.Invoke(thrownException, string.Join(Environment.NewLine, errors.ToArray())); } onEnd?.Invoke(); }
public void Run() { Exception thrownException = null; if (Process.StartInfo.RedirectStandardError) { Process.ErrorDataReceived += (s, e) => { //if (e.Data != null) //{ // Logger.Trace("ErrorData \"" + (e.Data == null ? "'null'" : e.Data) + "\""); //} string encodedData = null; if (e.Data != null) { encodedData = Encoding.UTF8.GetString(Encoding.Default.GetBytes(e.Data)); errors.Add(encodedData); } }; } try { Logger.Trace($"Running '{Process.StartInfo.FileName} {taskName}'"); Process.Start(); if (Process.StartInfo.RedirectStandardInput) { Input = new StreamWriter(Process.StandardInput.BaseStream, new UTF8Encoding(false)); } if (Process.StartInfo.RedirectStandardError) { Process.BeginErrorReadLine(); } onStart?.Invoke(); if (Process.StartInfo.RedirectStandardOutput) { var outputStream = Process.StandardOutput; var line = outputStream.ReadLine(); while (line != null) { outputProcessor.LineReceived(line); if (token.IsCancellationRequested) { if (!Process.HasExited) { Process.Kill(); } Process.Close(); token.ThrowIfCancellationRequested(); } line = outputStream.ReadLine(); } outputProcessor.LineReceived(null); } if (Process.StartInfo.CreateNoWindow) { while (!WaitForExit(500)) { if (token.IsCancellationRequested) { Process.Kill(); Process.Close(); } token.ThrowIfCancellationRequested(); } if (Process.ExitCode != 0 && errors.Count > 0) { thrownException = new ProcessException(Process.ExitCode, string.Join(Environment.NewLine, errors.ToArray())); } } } catch (Exception ex) { var errorCode = -42; if (ex is Win32Exception) { errorCode = ((Win32Exception)ex).NativeErrorCode; } StringBuilder sb = new StringBuilder(); sb.AppendLine($"Error code {errorCode}"); sb.AppendLine(ex.Message); if (Process.StartInfo.Arguments.Contains("-credential")) { sb.AppendLine($"'{Process.StartInfo.FileName} {taskName}'"); } else { sb.AppendLine($"'{Process.StartInfo.FileName} {Process.StartInfo.Arguments}'"); } if (errorCode == 2) { sb.AppendLine("The system cannot find the file specified."); } foreach (string env in Process.StartInfo.EnvironmentVariables.Keys) { sb.AppendFormat("{0}:{1}", env, Process.StartInfo.EnvironmentVariables[env]); sb.AppendLine(); } thrownException = new ProcessException(errorCode, sb.ToString(), ex); } if (thrownException != null || errors.Count > 0) { onError?.Invoke(thrownException, string.Join(Environment.NewLine, errors.ToArray())); } onEnd?.Invoke(); }