private ProcessOutput(Process process, Redirector redirector) { _arguments = QuoteSingleArgument(process.StartInfo.FileName) + " " + process.StartInfo.Arguments; _redirector = redirector; if (_redirector == null) { _output = new List<string>(); _error = new List<string>(); } _process = process; if (_process.StartInfo.RedirectStandardOutput) { _process.OutputDataReceived += OnOutputDataReceived; } if (_process.StartInfo.RedirectStandardError) { _process.ErrorDataReceived += OnErrorDataReceived; } if (!_process.StartInfo.RedirectStandardOutput && !_process.StartInfo.RedirectStandardError) { // If we are receiving output events, we signal that the process // has exited when one of them receives null. Otherwise, we have // to listen for the Exited event. // If we just listen for the Exited event, we may receive it // before all the output has arrived. _process.Exited += OnExited; } _process.EnableRaisingEvents = true; try { _process.Start(); } catch (Exception ex) { if (IsCriticalException(ex)) { throw; } if (_redirector != null) { foreach (var line in SplitLines(ex.ToString())) { _redirector.WriteErrorLine(line); } } else if (_error != null) { _error.AddRange(SplitLines(ex.ToString())); } _process = null; } if (_process != null) { if (_process.StartInfo.RedirectStandardOutput) { _process.BeginOutputReadLine(); } if (_process.StartInfo.RedirectStandardError) { _process.BeginErrorReadLine(); } if (_process.StartInfo.RedirectStandardInput) { // Close standard input so that we don't get stuck trying to read input from the user. try { _process.StandardInput.Close(); } catch (InvalidOperationException) { // StandardInput not available } } } }
/// <summary> /// Runs the file with the provided settings as a user with /// administrative permissions. The window is always hidden and output /// is provided to the redirector when the process terminates. /// </summary> /// <param name="filename">Executable file to run.</param> /// <param name="arguments">Arguments to pass.</param> /// <param name="workingDirectory">Starting directory.</param> /// <param name="redirector"> /// An object to receive redirected output. /// </param> /// <param name="quoteArgs"></param> /// <returns>A <see cref="ProcessOutput"/> object.</returns> public static ProcessOutput RunElevated( string filename, IEnumerable<string> arguments, string workingDirectory, Redirector redirector, bool quoteArgs = true, Encoding outputEncoding = null, Encoding errorEncoding = null ) { var outFile = Path.GetTempFileName(); var errFile = Path.GetTempFileName(); var psi = new ProcessStartInfo("cmd.exe"); psi.CreateNoWindow = true; psi.WindowStyle = ProcessWindowStyle.Hidden; psi.UseShellExecute = true; psi.Verb = "runas"; string args; if (quoteArgs) { args = string.Join(" ", arguments.Where(a => a != null).Select(QuoteSingleArgument)); } else { args = string.Join(" ", arguments.Where(a => a != null)); } psi.Arguments = string.Format("/S /C \"{0} {1} >>{2} 2>>{3}\"", QuoteSingleArgument(filename), args, QuoteSingleArgument(outFile), QuoteSingleArgument(errFile) ); psi.WorkingDirectory = workingDirectory; psi.CreateNoWindow = true; psi.UseShellExecute = true; var process = new Process(); process.StartInfo = psi; var result = new ProcessOutput(process, redirector); if (redirector != null) { result.Exited += (s, e) => { try { try { var lines = File.ReadAllLines(outFile, outputEncoding ?? Encoding.Default); foreach (var line in lines) { redirector.WriteLine(line); } } catch (Exception ex) { if (IsCriticalException(ex)) { throw; } redirector.WriteErrorLine("Failed to obtain standard output from elevated process."); #if DEBUG foreach (var line in SplitLines(ex.ToString())) { redirector.WriteErrorLine(line); } #else Trace.TraceError("Failed to obtain standard output from elevated process."); Trace.TraceError(ex.ToString()); #endif } try { var lines = File.ReadAllLines(errFile, errorEncoding ?? outputEncoding ?? Encoding.Default); foreach (var line in lines) { redirector.WriteErrorLine(line); } } catch (Exception ex) { if (IsCriticalException(ex)) { throw; } redirector.WriteErrorLine("Failed to obtain standard error from elevated process."); #if DEBUG foreach (var line in SplitLines(ex.ToString())) { redirector.WriteErrorLine(line); } #else Trace.TraceError("Failed to obtain standard error from elevated process."); Trace.TraceError(ex.ToString()); #endif } } finally { try { File.Delete(outFile); } catch { } try { File.Delete(errFile); } catch { } } }; } return result; }
/// <summary> /// Runs the file with the provided settings. /// </summary> /// <param name="filename">Executable file to run.</param> /// <param name="arguments">Arguments to pass.</param> /// <param name="workingDirectory">Starting directory.</param> /// <param name="env">Environment variables to set.</param> /// <param name="visible"> /// False to hide the window and redirect output to /// <see cref="StandardOutputLines"/> and /// <see cref="StandardErrorLines"/>. /// </param> /// <param name="redirector"> /// An object to receive redirected output. /// </param> /// <param name="quoteArgs"> /// True to ensure each argument is correctly quoted. /// </param> /// <param name="elevate"> /// True to run the process as an administrator. See /// <see cref="RunElevated"/>. /// </param> /// <returns>A <see cref="ProcessOutput"/> object.</returns> public static ProcessOutput Run( string filename, IEnumerable<string> arguments, string workingDirectory, IEnumerable<KeyValuePair<string, string>> env, bool visible, Redirector redirector, bool quoteArgs = true, bool elevate = false, Encoding outputEncoding = null, Encoding errorEncoding = null ) { if (string.IsNullOrEmpty(filename)) { throw new ArgumentException("Filename required", "filename"); } if (elevate) { return RunElevated( filename, arguments, workingDirectory, redirector, quoteArgs, outputEncoding, errorEncoding ); } var psi = new ProcessStartInfo(filename); if (quoteArgs) { psi.Arguments = string.Join(" ", arguments.Where(a => a != null).Select(QuoteSingleArgument)); } else { psi.Arguments = string.Join(" ", arguments.Where(a => a != null)); } psi.WorkingDirectory = workingDirectory; psi.CreateNoWindow = !visible; psi.UseShellExecute = false; psi.RedirectStandardError = !visible || (redirector != null); psi.RedirectStandardOutput = !visible || (redirector != null); psi.RedirectStandardInput = !visible; psi.StandardOutputEncoding = outputEncoding ?? psi.StandardOutputEncoding; psi.StandardErrorEncoding = errorEncoding ?? outputEncoding ?? psi.StandardErrorEncoding; if (env != null) { foreach (var kv in env) { psi.EnvironmentVariables[kv.Key] = kv.Value; } } var process = new Process { StartInfo = psi }; return new ProcessOutput(process, redirector); }
private ProcessOutput(Process process, Redirector redirector) { _arguments = QuoteSingleArgument(process.StartInfo.FileName) + " " + process.StartInfo.Arguments; _redirector = redirector; if (_redirector == null) { _output = new List <string>(); _error = new List <string>(); } _process = process; if (_process.StartInfo.RedirectStandardOutput) { _process.OutputDataReceived += OnOutputDataReceived; } if (_process.StartInfo.RedirectStandardError) { _process.ErrorDataReceived += OnErrorDataReceived; } if (!_process.StartInfo.RedirectStandardOutput && !_process.StartInfo.RedirectStandardError) { // If we are receiving output events, we signal that the process // has exited when one of them receives null. Otherwise, we have // to listen for the Exited event. // If we just listen for the Exited event, we may receive it // before all the output has arrived. _process.Exited += OnExited; } _process.EnableRaisingEvents = true; try { _process.Start(); } catch (Exception ex) { if (IsCriticalException(ex)) { throw; } if (_redirector != null) { foreach (var line in SplitLines(ex.ToString())) { _redirector.WriteErrorLine(line); } } else if (_error != null) { _error.AddRange(SplitLines(ex.ToString())); } _process = null; } if (_process != null) { if (_process.StartInfo.RedirectStandardOutput) { _process.BeginOutputReadLine(); } if (_process.StartInfo.RedirectStandardError) { _process.BeginErrorReadLine(); } if (_process.StartInfo.RedirectStandardInput) { // Close standard input so that we don't get stuck trying to read input from the user. try { _process.StandardInput.Close(); } catch (InvalidOperationException) { // StandardInput not available } } } }
/// <summary> /// Runs the file with the provided settings as a user with /// administrative permissions. The window is always hidden and output /// is provided to the redirector when the process terminates. /// </summary> /// <param name="filename">Executable file to run.</param> /// <param name="arguments">Arguments to pass.</param> /// <param name="workingDirectory">Starting directory.</param> /// <param name="redirector"> /// An object to receive redirected output. /// </param> /// <param name="quoteArgs"></param> /// <returns>A <see cref="ProcessOutput"/> object.</returns> public static ProcessOutput RunElevated( string filename, IEnumerable <string> arguments, string workingDirectory, Redirector redirector, bool quoteArgs = true, Encoding outputEncoding = null, Encoding errorEncoding = null ) { var outFile = Path.GetTempFileName(); var errFile = Path.GetTempFileName(); var psi = new ProcessStartInfo("cmd.exe"); psi.CreateNoWindow = true; psi.WindowStyle = ProcessWindowStyle.Hidden; psi.UseShellExecute = true; psi.Verb = "runas"; string args; if (quoteArgs) { args = string.Join(" ", arguments.Where(a => a != null).Select(QuoteSingleArgument)); } else { args = string.Join(" ", arguments.Where(a => a != null)); } psi.Arguments = string.Format("/S /C \"{0} {1} >>{2} 2>>{3}\"", QuoteSingleArgument(filename), args, QuoteSingleArgument(outFile), QuoteSingleArgument(errFile) ); psi.WorkingDirectory = workingDirectory; psi.CreateNoWindow = true; psi.UseShellExecute = true; var process = new Process(); process.StartInfo = psi; var result = new ProcessOutput(process, redirector); if (redirector != null) { result.Exited += (s, e) => { try { try { var lines = File.ReadAllLines(outFile, outputEncoding ?? Encoding.Default); foreach (var line in lines) { redirector.WriteLine(line); } } catch (Exception ex) { if (IsCriticalException(ex)) { throw; } redirector.WriteErrorLine("Failed to obtain standard output from elevated process."); #if DEBUG foreach (var line in SplitLines(ex.ToString())) { redirector.WriteErrorLine(line); } #else Trace.TraceError("Failed to obtain standard output from elevated process."); Trace.TraceError(ex.ToString()); #endif } try { var lines = File.ReadAllLines(errFile, errorEncoding ?? outputEncoding ?? Encoding.Default); foreach (var line in lines) { redirector.WriteErrorLine(line); } } catch (Exception ex) { if (IsCriticalException(ex)) { throw; } redirector.WriteErrorLine("Failed to obtain standard error from elevated process."); #if DEBUG foreach (var line in SplitLines(ex.ToString())) { redirector.WriteErrorLine(line); } #else Trace.TraceError("Failed to obtain standard error from elevated process."); Trace.TraceError(ex.ToString()); #endif } } finally { try { File.Delete(outFile); } catch { } try { File.Delete(errFile); } catch { } } }; } return(result); }
/// <summary> /// Runs the file with the provided settings. /// </summary> /// <param name="filename">Executable file to run.</param> /// <param name="arguments">Arguments to pass.</param> /// <param name="workingDirectory">Starting directory.</param> /// <param name="env">Environment variables to set.</param> /// <param name="visible"> /// False to hide the window and redirect output to /// <see cref="StandardOutputLines"/> and /// <see cref="StandardErrorLines"/>. /// </param> /// <param name="redirector"> /// An object to receive redirected output. /// </param> /// <param name="quoteArgs"> /// True to ensure each argument is correctly quoted. /// </param> /// <param name="elevate"> /// True to run the process as an administrator. See /// <see cref="RunElevated"/>. /// </param> /// <returns>A <see cref="ProcessOutput"/> object.</returns> public static ProcessOutput Run( string filename, IEnumerable <string> arguments, string workingDirectory, IEnumerable <KeyValuePair <string, string> > env, bool visible, Redirector redirector, bool quoteArgs = true, bool elevate = false, Encoding outputEncoding = null, Encoding errorEncoding = null ) { if (string.IsNullOrEmpty(filename)) { throw new ArgumentException("Filename required", "filename"); } if (elevate) { return(RunElevated( filename, arguments, workingDirectory, redirector, quoteArgs, outputEncoding, errorEncoding )); } var psi = new ProcessStartInfo(filename); if (quoteArgs) { psi.Arguments = string.Join(" ", arguments.Where(a => a != null).Select(QuoteSingleArgument)); } else { psi.Arguments = string.Join(" ", arguments.Where(a => a != null)); } psi.WorkingDirectory = workingDirectory; psi.CreateNoWindow = !visible; psi.UseShellExecute = false; psi.RedirectStandardError = !visible || (redirector != null); psi.RedirectStandardOutput = !visible || (redirector != null); psi.RedirectStandardInput = !visible; psi.StandardOutputEncoding = outputEncoding ?? psi.StandardOutputEncoding; psi.StandardErrorEncoding = errorEncoding ?? outputEncoding ?? psi.StandardErrorEncoding; if (env != null) { foreach (var kv in env) { psi.EnvironmentVariables[kv.Key] = kv.Value; } } var process = new Process { StartInfo = psi }; return(new ProcessOutput(process, redirector)); }