/// <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(Path.Combine(Environment.SystemDirectory, "cmd.exe")) { CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, UseShellExecute = true, 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 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; }