public ProcessWrapper(string fileName, string arguments, string workDir, bool createWindow, bool redirectInput, bool redirectOutput, Encoding?outputEncoding, bool useShellExecute) { Debug.Assert(redirectOutput == (outputEncoding is not null), "redirectOutput == (outputEncoding is not null)"); _redirectInput = redirectInput; _redirectOutput = redirectOutput; _process = new Process { EnableRaisingEvents = true, StartInfo = { UseShellExecute = useShellExecute, Verb = useShellExecute ? "open" : string.Empty, ErrorDialog = false, CreateNoWindow = !createWindow, RedirectStandardInput = redirectInput, RedirectStandardOutput = redirectOutput, RedirectStandardError = redirectOutput, StandardOutputEncoding = outputEncoding, StandardErrorEncoding = outputEncoding, FileName = fileName, Arguments = arguments, WorkingDirectory = workDir } }; _logOperation = CommandLog.LogProcessStart(fileName, arguments, workDir); _process.Exited += OnProcessExit; try { _process.Start(); try { _logOperation.SetProcessId(_process.Id); } catch (InvalidOperationException ex) when(useShellExecute) { // _process.Start() has succeeded, ignore the failure getting the _process.Id _logOperation.LogProcessEnd(ex); } } catch (Exception ex) { Dispose(); _logOperation.LogProcessEnd(ex); throw new ExternalOperationException(fileName, arguments, workDir, ex); } }
public override void StartProcess(string command, string arguments, string workDir, Dictionary <string, string> envVariables) { ProcessOperation operation = CommandLog.LogProcessStart(command, arguments, workDir); try { var commandLine = new ArgumentBuilder { command.Quote(), arguments }.ToString(); ConsoleCommandLineOutputProcessor outputProcessor = new(commandLine.Length, FireDataReceived); ConEmuStartInfo startInfo = new() { ConsoleProcessCommandLine = commandLine, IsEchoingConsoleCommandLine = true, WhenConsoleProcessExits = WhenConsoleProcessExits.KeepConsoleEmulatorAndShowMessage, AnsiStreamChunkReceivedEventSink = outputProcessor.AnsiStreamChunkReceived, StartupDirectory = workDir }; foreach (var(name, value) in envVariables) { startInfo.SetEnv(name, value); } startInfo.ConsoleProcessExitedEventSink = (_, args) => { _nLastExitCode = args.ExitCode; operation.LogProcessEnd(_nLastExitCode); outputProcessor.Flush(); FireProcessExited(); }; startInfo.ConsoleEmulatorClosedEventSink = (sender, _) => { Validates.NotNull(_terminal); if (sender == _terminal.RunningSession) { FireTerminated(); } }; Validates.NotNull(_terminal); _terminal.Start(startInfo, ThreadHelper.JoinableTaskFactory, AppSettings.ConEmuStyle.Value, AppSettings.ConEmuConsoleFont.Name, AppSettings.ConEmuConsoleFont.Size.ToString(CultureInfo.InvariantCulture)); } catch (Exception ex) { operation.LogProcessEnd(ex); throw; } }
private void OnProcessExit(object sender, EventArgs eventArgs) { // The Exited event can be raised after the process is disposed, however // if the Process is disposed then reading ExitCode will throw. if (_disposed == 0) { ExitCode = _process.ExitCode; } _logOperation.LogProcessEnd(ExitCode); _exitTaskCompletionSource.TrySetResult(ExitCode); }
private void OnProcessExit(object sender, EventArgs eventArgs) { lock (_syncRoot) { // The Exited event can be raised after the process is disposed, however // if the Process is disposed then reading ExitCode will throw. if (!_disposed) { try { var exitCode = _process.ExitCode; _logOperation.LogProcessEnd(exitCode); _exitTaskCompletionSource.TrySetResult(exitCode); } catch (Exception ex) { _logOperation.LogProcessEnd(ex); _exitTaskCompletionSource.TrySetException(ex); } } } }
public ProcessWrapper(string fileName, string arguments, string workDir, bool createWindow, bool redirectInput, bool redirectOutput, [CanBeNull] Encoding outputEncoding, bool useShellExecute) { Debug.Assert(redirectOutput == (outputEncoding != null), "redirectOutput == (outputEncoding != null)"); _redirectInput = redirectInput; _redirectOutput = redirectOutput; _process = new Process { EnableRaisingEvents = true, StartInfo = { UseShellExecute = useShellExecute, ErrorDialog = false, CreateNoWindow = !createWindow, RedirectStandardInput = redirectInput, RedirectStandardOutput = redirectOutput, RedirectStandardError = redirectOutput, StandardOutputEncoding = outputEncoding, StandardErrorEncoding = outputEncoding, FileName = fileName, Arguments = arguments, WorkingDirectory = workDir } }; _logOperation = CommandLog.LogProcessStart(fileName, arguments, workDir); _process.Exited += OnProcessExit; try { _process.Start(); _logOperation.SetProcessId(_process.Id); } catch (Exception ex) { Dispose(); _logOperation.LogProcessEnd(ex); throw new ExternalOperationException(fileName, arguments, workDir, ex); } }
public override void StartProcess(string command, string arguments, string workDir, Dictionary <string, string> envVariables) { ProcessOperation operation = CommandLog.LogProcessStart(command, arguments, workDir); try { EnvironmentConfiguration.SetEnvironmentVariables(); bool ssh = GitSshHelpers.UseSsh(arguments); KillProcess(); // process used to execute external commands var outputEncoding = GitModule.SystemEncoding; var startInfo = new ProcessStartInfo { UseShellExecute = false, ErrorDialog = false, CreateNoWindow = !ssh && !AppSettings.ShowGitCommandLine, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, StandardOutputEncoding = outputEncoding, StandardErrorEncoding = outputEncoding, FileName = command, Arguments = arguments, WorkingDirectory = workDir }; foreach (var(name, value) in envVariables) { startInfo.EnvironmentVariables.Add(name, value); } var process = new Process { StartInfo = startInfo, EnableRaisingEvents = true }; process.OutputDataReceived += (sender, args) => FireDataReceived(new TextEventArgs((args.Data ?? "") + '\n')); process.ErrorDataReceived += (sender, args) => FireDataReceived(new TextEventArgs((args.Data ?? "") + '\n')); process.Exited += delegate { this.InvokeAsync( () => { if (_process is null) { operation.LogProcessEnd(new Exception("Process instance is null in Exited event")); return; } // The process is exited already, but this command waits also until all output is received. // Only WaitForExit when someone is connected to the exited event. For some reason a // null reference is thrown sometimes when staging/unstaging in the commit dialog when // we wait for exit, probably a timing issue... try { _process.WaitForExit(); } catch (Exception ex) { operation.LogProcessEnd(ex); } _exitcode = _process.ExitCode; operation.LogProcessEnd(_exitcode); _process = null; _outputThrottle?.FlushOutput(); FireProcessExited(); _outputThrottle?.Stop(flush: true); }).FileAndForget(); }; process.Start(); operation.SetProcessId(process.Id); _process = process; process.BeginOutputReadLine(); process.BeginErrorReadLine(); } catch (Exception ex) { operation.LogProcessEnd(ex); ex.Data.Add("command", command); ex.Data.Add("arguments", arguments); throw; } }