/// <summary> /// Create a <see cref="IProcess"/> given an existing <paramref name="handle"/>. /// </summary> /// <param name="handle">The <see cref="global::System.Diagnostics.Process"/> to create a <see cref="IProcess"/> from.</param> /// <returns>The <see cref="IProcess"/> based on <paramref name="handle"/>.</returns> private IProcess CreateFromExistingHandle(global::System.Diagnostics.Process handle) { try { var pid = handle.Id; return(new Process( processFeatures, handle, AttachExitHandler(handle, () => pid), null, null, null, loggerFactory.CreateLogger <Process>(), true)); } catch { handle.Dispose(); throw; } }
/// <inheritdoc /> public IProcess LaunchProcess(string fileName, string workingDirectory, string arguments, bool readOutput, bool readError, bool noShellExecute) { logger.LogDebug("Launching process in {0}: {1} {2}", workingDirectory, fileName, arguments); var handle = new global::System.Diagnostics.Process(); try { handle.StartInfo.FileName = fileName; handle.StartInfo.Arguments = arguments; handle.StartInfo.WorkingDirectory = workingDirectory; handle.StartInfo.UseShellExecute = !(noShellExecute || readOutput || readError); StringBuilder outputStringBuilder = null, errorStringBuilder = null, combinedStringBuilder = null; if (readOutput || readError) { combinedStringBuilder = new StringBuilder(); if (readOutput) { outputStringBuilder = new StringBuilder(); handle.StartInfo.RedirectStandardOutput = true; handle.OutputDataReceived += (sender, e) => { combinedStringBuilder.Append(Environment.NewLine); combinedStringBuilder.Append(e.Data); outputStringBuilder.Append(Environment.NewLine); outputStringBuilder.Append(e.Data); }; } if (readError) { errorStringBuilder = new StringBuilder(); handle.StartInfo.RedirectStandardError = true; handle.ErrorDataReceived += (sender, e) => { combinedStringBuilder.Append(Environment.NewLine); combinedStringBuilder.Append(e.Data); errorStringBuilder.Append(Environment.NewLine); errorStringBuilder.Append(e.Data); }; } } var lifetimeTask = AttachExitHandler(handle); handle.Start(); try { if (readOutput) { handle.BeginOutputReadLine(); } } catch (InvalidOperationException) { } try { if (readError) { handle.BeginErrorReadLine(); } } catch (InvalidOperationException) { } return(new Process(handle, lifetimeTask, outputStringBuilder, errorStringBuilder, combinedStringBuilder, loggerFactory.CreateLogger <Process>(), false)); } catch { handle.Dispose(); throw; } }
/// <inheritdoc /> public IProcess LaunchProcess( string fileName, string workingDirectory, string arguments, bool readOutput, bool readError, bool noShellExecute) { if (fileName == null) { throw new ArgumentNullException(nameof(fileName)); } if (workingDirectory == null) { throw new ArgumentNullException(nameof(workingDirectory)); } if (arguments == null) { throw new ArgumentNullException(nameof(arguments)); } if (!noShellExecute && (readOutput || readError)) { throw new InvalidOperationException("Requesting output/error reading requires noShellExecute to be true!"); } logger.LogDebug( "{0}aunching process in {1}: {2} {3}", noShellExecute ? "L" : "Shell l", workingDirectory, fileName, arguments); var handle = new global::System.Diagnostics.Process(); try { handle.StartInfo.FileName = fileName; handle.StartInfo.Arguments = arguments; handle.StartInfo.WorkingDirectory = workingDirectory; handle.StartInfo.UseShellExecute = !noShellExecute; StringBuilder combinedStringBuilder = null; Task <string> outputTask = null; Task <string> errorTask = null; var processStartTcs = new TaskCompletionSource <object>(); if (readOutput || readError) { combinedStringBuilder = new StringBuilder(); async Task <string> ConsumeReader(Func <TextReader> readerFunc) { var stringBuilder = new StringBuilder(); string text; await processStartTcs.Task.ConfigureAwait(false); var reader = readerFunc(); while ((text = await reader.ReadLineAsync().ConfigureAwait(false)) != null) { combinedStringBuilder.AppendLine(); combinedStringBuilder.Append(text); stringBuilder.AppendLine(); stringBuilder.Append(text); } return(stringBuilder.ToString()); } if (readOutput) { outputTask = ConsumeReader(() => handle.StandardOutput); handle.StartInfo.RedirectStandardOutput = true; } if (readError) { errorTask = ConsumeReader(() => handle.StandardError); handle.StartInfo.RedirectStandardError = true; } } var lifetimeTaskTask = AttachExitHandlerBeforeLaunch(handle, processStartTcs.Task); try { handle.Start(); processStartTcs.SetResult(null); } catch (Exception ex) { processStartTcs.SetException(ex); throw; } var process = new Process( processFeatures, handle, lifetimeTaskTask.GetAwaiter().GetResult(), // won't block outputTask, errorTask, combinedStringBuilder, loggerFactory.CreateLogger <Process>(), false); return(process); } catch { handle.Dispose(); throw; } }