/// <summary> /// Executes the <paramref name="executable"/> and waits a maximum time of <paramref name="maxWaitMs"/> for completion. If the process doesn't end in /// this time, it gets aborted. This method tries to impersonate the interactive user and run the process under its identity. /// </summary> /// <param name="executable">Program to execute</param> /// <param name="arguments">Program arguments</param> /// <param name="token">User token to run process</param> /// <param name="redirectInputOutput"><c>true</c> to redirect standard streams.</param> /// <param name="result">Returns the contents of standard output.</param> /// <param name="priorityClass">Process priority</param> /// <param name="maxWaitMs">Maximum time to wait for completion</param> /// <returns><c>true</c> if process was executed and finished correctly</returns> private static bool TryExecute_Impersonated(string executable, string arguments, IntPtr token, bool redirectInputOutput, out string result, ProcessPriorityClass priorityClass = ProcessPriorityClass.Normal, int maxWaitMs = INFINITE) { // Note: Althought the code is nearly identical as TryExecute, it cannot be easily refactored, as the ImpersonationProcess implements many methods and properties with "new". // If such an instance is assigned to "Process" base class, any access will fail here. StringBuilder outputBuilder = new StringBuilder(); using (ImpersonationProcess process = new ImpersonationProcess()) using (AutoResetEvent outputWaitHandle = new AutoResetEvent(!redirectInputOutput)) { PrepareProcess(executable, arguments, redirectInputOutput, process, outputWaitHandle, outputBuilder); process.StartAsUser(token); if (!process.HasExited) { process.PriorityClass = priorityClass; } if (redirectInputOutput) { process.BeginOutputReadLine(); } if (process.WaitForExit(maxWaitMs) && outputWaitHandle.WaitOne(maxWaitMs)) { if (redirectInputOutput) { process.CancelOutputRead(); } result = RemoveEncodingPreamble(outputBuilder.ToString()); return(process.ExitCode == 0); } if (!process.HasExited) { if (redirectInputOutput) { process.CancelOutputRead(); } process.Kill(); } } result = null; return(false); }
/// <summary> /// Executes the <paramref name="executable"/> and waits a maximum time of <paramref name="maxWaitMs"/> for completion. If the process doesn't end in /// this time, it gets aborted. This method tries to impersonate the interactive user and run the process under its identity. /// </summary> /// <param name="executable">Program to execute</param> /// <param name="arguments">Program arguments</param> /// <param name="token">User token to run process</param> /// <param name="redirectInputOutput"><c>true</c> to redirect standard streams.</param> /// <param name="result">Returns the contents of standard output.</param> /// <param name="priorityClass">Process priority</param> /// <param name="maxWaitMs">Maximum time to wait for completion</param> /// <returns><c>true</c> if process was executed and finished correctly</returns> private static bool TryExecute_Impersonated(string executable, string arguments, IntPtr token, bool redirectInputOutput, out string result, ProcessPriorityClass priorityClass = ProcessPriorityClass.Normal, int maxWaitMs = INFINITE) { // TODO: code is 99% redundant to TryExecute, refactor Process/ImpersonationProcess and Start/StartAsUser! StringBuilder outputBuilder = new StringBuilder(); using (ImpersonationProcess process = new ImpersonationProcess { StartInfo = new ProcessStartInfo(executable, arguments) { UseShellExecute = false, CreateNoWindow = true, RedirectStandardOutput = redirectInputOutput } }) { if (redirectInputOutput) { // Set UTF-8 encoding for standard output. process.StartInfo.StandardOutputEncoding = CONSOLE_ENCODING; // Enable raising events because Process does not raise events by default. process.EnableRaisingEvents = true; // Attach the event handler for OutputDataReceived before starting the process. process.OutputDataReceived += (sender, e) => outputBuilder.Append(e.Data); } process.StartAsUser(token); process.PriorityClass = priorityClass; if (redirectInputOutput) process.BeginOutputReadLine(); if (process.WaitForExit(maxWaitMs)) { result = RemoveEncodingPreamble(outputBuilder.ToString()); return process.ExitCode == 0; } if (!process.HasExited) process.Kill(); } result = null; return false; }
private static bool TryExecute_Impersonated(string executable, string arguments, IntPtr token, bool redirectInputOutput, out string result, ProcessPriorityClass priorityClass = ProcessPriorityClass.Normal, int maxWaitMs = DEFAULT_TIMEOUT) { // Note: Althought the code is nearly identical as TryExecute, it cannot be easily refactored, as the ImpersonationProcess implements many methods and properties with "new". // If such an instance is assigned to "Process" base class, any access will fail here. StringBuilder outputBuilder = new StringBuilder(); using (ImpersonationProcess process = new ImpersonationProcess()) using (AutoResetEvent outputWaitHandle = new AutoResetEvent(!redirectInputOutput)) { PrepareProcess(executable, arguments, redirectInputOutput, process, outputWaitHandle, outputBuilder); process.StartAsUser(token); if (!process.HasExited) process.PriorityClass = priorityClass; if (redirectInputOutput) process.BeginOutputReadLine(); if (process.WaitForExit(maxWaitMs) && outputWaitHandle.WaitOne(maxWaitMs)) { if (redirectInputOutput) process.CancelOutputRead(); result = RemoveEncodingPreamble(outputBuilder.ToString()); return process.ExitCode == 0; } if (!process.HasExited) { if (redirectInputOutput) process.CancelOutputRead(); process.Kill(); } } result = null; return false; }