public bool WaitForExit(int millisecondsTimeout) { if (hasExited) { return(true); } if (!wasStarted) { throw new InvalidOperationException("Process was not yet started"); } if (safeProcessHandle.IsClosed) { throw new ObjectDisposedException("ProcessRunner"); } using (var waitHandle = new ProcessWaitHandle(safeProcessHandle)) { if (waitHandle.WaitOne(millisecondsTimeout, false)) { if (!GetExitCodeProcess(safeProcessHandle, out exitCode)) { throw new Win32Exception(); } // Wait until the output is processed // if (standardOutputTask != null) // standardOutputTask.Wait(); // if (standardErrorTask != null) // standardErrorTask.Wait(); hasExited = true; } } return(hasExited); }
/// <summary> /// Asynchronously waits for the process to exit. /// </summary> public Task WaitForExitAsync() { if (hasExited) { return(Task.FromResult(true)); } if (!wasStarted) { throw new InvalidOperationException("Process was not yet started"); } if (safeProcessHandle.IsClosed) { throw new ObjectDisposedException("ProcessRunner"); } lock (lockObj) { if (waitForExitTCS == null) { waitForExitTCS = new TaskCompletionSource <object>(); waitForExitAsyncWaitHandle = new ProcessWaitHandle(safeProcessHandle); waitForExitAsyncRegisteredWaitHandle = ThreadPool.RegisterWaitForSingleObject(waitForExitAsyncWaitHandle, WaitForExitAsyncCallback, null, -1, true); } return(waitForExitTCS.Task); } }
IntPtr GetProcessHandle(Kernel32.ProcessAccessFlags access, bool throwIfExited) { if (_haveProcessHandle) { if (throwIfExited) { // Since haveProcessHandle is true, we know we have the process handle // open with at least SYNCHRONIZE access, so we can wait on it with // zero timeout to see if the process has exited. ProcessWaitHandle waitHandle = null; try { waitHandle = new ProcessWaitHandle(_processHandle); if (waitHandle.WaitOne(0, false)) { throw new InvalidOperationException("Process has exited"); } } finally { waitHandle?.Close(); } } return(_processHandle); } var handle = Kernel32.OpenProcess(access, false, _inner.Id); if (throwIfExited && (access & Kernel32.ProcessAccessFlags.QueryInformation) != 0) { if (Kernel32.GetExitCodeProcess(handle, out var exitCode) && exitCode != Kernel32.STILL_ACTIVE) { throw new InvalidOperationException("Process has exited"); } } return(handle); }
/// <summary> /// Asynchronously waits for the process to exit. /// </summary> public static Task WaitForExitAsync(this Process process) { if (process.HasExited) { return(Task.CompletedTask); } var safeProcessHandle = process.SafeHandle; if (safeProcessHandle.IsClosed) { throw new ObjectDisposedException("Process"); } var tcs = new TaskCompletionSource <object?>(); var waitHandle = new ProcessWaitHandle(safeProcessHandle); RegisteredWaitHandle?registeredWaitHandle = null; lock (tcs) { registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(waitHandle, WaitForExitAsyncCallback, null, -1, true); } return(tcs.Task); void WaitForExitAsyncCallback(object context, bool wasSignaled) { // The lock is used to ensure `registeredWaitHandle` is initialized here // even if the process terminates while `RegisterWaitForSingleObject` is returning. lock (tcs) { registeredWaitHandle !.Unregister(null); } waitHandle.Close(); tcs.SetResult(null); } }
public bool WaitForExit(int exitTime = -1) { using (var wait = new ProcessWaitHandle(proc)) { return(wait.WaitOne(exitTime)); } }
public bool WaitForExit(TimeSpan timeout) { if (IsInvalid || IsClosed) { return(true); } using (var waitHandle = new ProcessWaitHandle(this)) { return(waitHandle.WaitOne(timeout)); } }
private void WaitForExitAsyncCallback(object context, bool wasSignaled) { waitForExitAsyncRegisteredWaitHandle.Unregister(null); waitForExitAsyncRegisteredWaitHandle = null; waitForExitAsyncWaitHandle.Close(); waitForExitAsyncWaitHandle = null; // Wait until the output is processed // if (standardOutputTask != null) // await standardOutputTask; // if (standardErrorTask != null) // await standardErrorTask; waitForExitTCS.SetResult(null); }
private void MonitorBrokerProcess() { var monitoringHandles = new WaitHandle[2]; monitoringHandles[0] = _stopSignal; int relaunchCount = 0; int pauseBeforeRelaunch = 0; while (true) { try { _logger.Info("Waiting for stop signal or broker process termination"); // launch/re-launch/get JSI process monitoringHandles[1] = new ProcessWaitHandle(GetMessageBrokerProcess().Handle); // Wait for stop signal or broker process termination var signaledIndex = WaitHandle.WaitAny(monitoringHandles); // If, stop signal recieved, stop monitoring if (signaledIndex == 0) { _logger.Info("Received stop signal. Stopping the monitoring of broker process."); // Release the monitoring mutex _monitoringOwnershipMutex.ReleaseMutex(); return; } // After every 20 relaunches we reset if (relaunchCount > 20) { relaunchCount = 0; } relaunchCount++; // For each relaunch increase the pause time between relaunches by 2 seconds pauseBeforeRelaunch = relaunchCount * 2; _logger.Info(string.Format("The broker process will restart in {0} seconds", pauseBeforeRelaunch)); Thread.Sleep(pauseBeforeRelaunch * 1000); } catch (Exception ex) { _logger.Error("Error monitoring broker process. Trying again", ex); } } }
static void Main(string[] args) { const int numProcesses = 5; var processes = new ProcessWaitHandle[numProcesses]; for (int i = 0; i < numProcesses; i++) { var process = Process.Start(i % 2 == 0 ? "notepad" : "mspaint"); Console.WriteLine($"Started {process.ProcessName} (PID={process.Id}..."); processes[i] = new ProcessWaitHandle(process); } Console.WriteLine("Waiting for these processes to exit..."); WaitHandle.WaitAll(processes); Console.WriteLine("All processes exited!"); }
static void Main(string[] args) { int processesCount = 42; var processes = new Process[processesCount]; var waitHandles = new WaitHandle[processesCount]; try { for (int i = 0; processesCount > i; ++i) { // exit immediately with return code i Process process = Process.Start( "cmd.exe", Invariant($"/C \"exit {i}\"")); processes[i] = process; waitHandles[i] = new ProcessWaitHandle(process); } WaitHandle.WaitAll(waitHandles); foreach (Process p in processes) { Console.Error.WriteLine( Invariant($"process with Id {p.Id} exited with code {p.ExitCode}")); } } finally { foreach (Process p in processes) { p?.Dispose(); } foreach (WaitHandle h in waitHandles) { h?.Dispose(); } } Console.WriteLine("Press any key to continue..."); Console.ReadKey(false); }
public bool WaitForExitSafe(int milliseconds) { var handle = IntPtr.Zero; bool exited; ProcessWaitHandle processWaitHandle = null; try { handle = GetProcessHandle(Kernel32.ProcessAccessFlags.Synchronize, false); if (handle == IntPtr.Zero || handle == new IntPtr(-1)) { exited = true; } else { processWaitHandle = new ProcessWaitHandle(handle); if (processWaitHandle.WaitOne(milliseconds, false)) { exited = true; _signaled = true; } else { exited = false; _signaled = false; } } } finally { processWaitHandle?.Close(); ReleaseProcessHandle(handle); } if (exited && _watchForExit) { RaiseOnExited(); } return(exited); }
} // proc CreateProcessPipe public bool StartProcess() { var errorLogged = false; try { if (IsProcessRunning) { StopProcess(); } SafeFileHandle hInput = null; SafeFileHandle hOutput = null; SafeFileHandle hError = null; var hEnvironment = default(GCHandle); using (var msg = Log.GetScope(LogMsgType.Information, stopTime: true)) using (var startupInfo = new NativeMethods.STARTUPINFO()) { msg.WriteLine("Start process..."); try { // Create command line var command = new StringBuilder(); var fileName = ConfigNode.GetAttribute <string>("filename"); if (!String.IsNullOrEmpty(fileName)) { if (fileName.Length > 0 && fileName[0] == '"' && fileName[fileName.Length] == '"') { command.Append(fileName); } else { command.Append('"').Append(fileName).Append('"'); } } var argumentsAttr = Config.GetAttribute("arguments", String.Empty); if (!String.IsNullOrEmpty(argumentsAttr)) { command.Append(' ').Append(argumentsAttr); } var argumentsElement = Config.Element(xnArguments); if (argumentsElement != null && !String.IsNullOrEmpty(argumentsElement.Value)) { command.Append(' ').Append(argumentsElement.Value); } if (command.Length == 0) { throw new ArgumentException("@filename", "Filename is missing."); } // Working-Directory var workingDirectory = Config.GetAttribute("workingDirectory", null); // Run program as a different user var domain = ConfigNode.GetAttribute <string>("domain"); var userName = ConfigNode.GetAttribute <string>("username"); var password = ConfigNode.GetAttribute <SecureString>("password"); if (!String.IsNullOrEmpty(userName)) { msg.WriteLine("Logon user..."); using (var pPassword = password.GetPasswordHandle()) { if (!NativeMethods.LogonUser(userName, domain, pPassword.DangerousGetHandle(), Environment.UserInteractive ? NativeMethods.LOGON_TYPE.LOGON32_LOGON_INTERACTIVE : NativeMethods.LOGON_TYPE.LOGON32_LOGON_SERVICE, NativeMethods.LOGON_PROVIDER.LOGON32_PROVIDER_DEFAULT, out hUser)) { throw new Win32Exception(); } } } // Create environment for the user msg.WriteLine("Create environment..."); hEnvironment = GCHandle.Alloc(CreateEnvironment(hUser, userName, ConfigNode.GetAttribute <bool>("loadUserProfile")), GCHandleType.Pinned); // Flags for the process var flags = NativeMethods.CREATE_PROCESS_FLAGS.CREATE_NEW_PROCESS_GROUP | NativeMethods.CREATE_PROCESS_FLAGS.CREATE_NO_WINDOW | NativeMethods.CREATE_PROCESS_FLAGS.CREATE_UNICODE_ENVIRONMENT | NativeMethods.CREATE_PROCESS_FLAGS.CREATE_SUSPENDED; // Create start parameter msg.WriteLine("Create pipes..."); startupInfo.dwFlags = 0x00000100; CreateProcessPipe(true, out hInput, out startupInfo.hStdInput); CreateProcessPipe(false, out hOutput, out startupInfo.hStdOutput); CreateProcessPipe(false, out hError, out startupInfo.hStdError); startupInfo.lpDesktop = String.Empty; var processinformation = new NativeMethods.PROCESS_INFORMATION(); try { if (hUser == IntPtr.Zero) { msg.WriteLine("Create process..."); if (!NativeMethods.CreateProcess(null, command, null, null, true, flags, hEnvironment.AddrOfPinnedObject(), workingDirectory, startupInfo, processinformation)) { throw new Win32Exception(); } } else { // user32.dll failed to initialize under system context? msg.WriteLine("Create process as user..."); if (!NativeMethods.CreateProcessAsUser(hUser, null, command, null, null, true, flags, hEnvironment.AddrOfPinnedObject(), workingDirectory, startupInfo, processinformation)) { throw new Win32Exception(); } //if (!NativeMethods.CreateProcessWithTokenW(hUser, 1, null, command, flags, hEnvironment.AddrOfPinnedObject(), workingDirectory, startupInfo, processinformation)) // throw new Win32Exception(); } // Create the .net process-objekt process = Process.GetProcessById(processinformation.dwProcessId); msg.WriteLine("Process crreated (ProcessId: {0}; Session: {1})", process.Id, process.SessionId); // Create pipes var inputEncoding = Config.Attribute("inputEncoding") == null ? null : ConfigNode.GetAttribute <Encoding>("inputEncoding"); var outputEncoding = Config.Attribute("outputEncoding") == null ? null : ConfigNode.GetAttribute <Encoding>("outputEncoding"); inputStream = new StreamWriter(new FileStream(hInput, FileAccess.Write, 4096, false), inputEncoding ?? Console.InputEncoding) { AutoFlush = true }; outputStream = new StreamReader(new FileStream(hOutput, FileAccess.Read, 4096, false), outputEncoding ?? Console.OutputEncoding); errorStream = new StreamReader(new FileStream(hError, FileAccess.Read, 4096, false), outputEncoding ?? Console.OutputEncoding); exitWaitHandle = new ProcessWaitHandle(processinformation.hProcess); waitForExitEvent = new ManualResetEventSlim(false); waitHandle = ThreadPool.RegisterWaitForSingleObject(exitWaitHandle, ProcessExited, process, -1, true); arOutputStream = procProcessLogLine.BeginInvoke(LogMsgType.Information, outputStream, null, outputStream); arErrorStream = procProcessLogLine.BeginInvoke(LogMsgType.Warning, errorStream, null, errorStream); // Run application msg.WriteLine("Resume process..."); NativeMethods.ResumeThread(processinformation.hThread); } finally { NativeMethods.CloseHandle(processinformation.hThread); } msg.WriteLine("Successful loaded."); } catch (Exception e) { if (hUser != IntPtr.Zero) { NativeMethods.CloseHandle(hUser); } if (hInput != null && !hInput.IsInvalid) { hInput.Close(); } if (hOutput != null && !hOutput.IsInvalid) { hOutput.Close(); } if (hError != null && !hError.IsInvalid) { hError.Close(); } msg.WriteException(e); errorLogged = true; throw; } finally { if (hEnvironment.IsAllocated) { hEnvironment.Free(); } } } CallMemberDirect("ProcessStarted", new object[] { process }, throwExceptions: false); HttpRefreshProperties(); return(true); } catch (Exception e) { if (!errorLogged) { Log.LogMsg(LogMsgType.Error, e.GetMessageString()); } return(false); } } // proc StartProcess
public int Run() { STARTUPINFO si = new STARTUPINFO(); si.lpDesktop = this.Desktop; PROCESSINFO pi = new PROCESSINFO(); int creationFlags = NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT; creationFlags |= this.CreateNoWindow ? CREATE_NO_WINDOW : 0; // This creates the default environment block for this user. If you need // something custom skip te CreateEnvironmentBlock (and DestroyEnvironmentBlock) // calls. You need to handle the allocation of the memory and writing to // it yourself. IntPtr envBlock; if (!CreateEnvironmentBlock(out envBlock, this.mSessionTokenHandle, 0)) { throw new System.ComponentModel.Win32Exception(); } try { CreateProcessAsUser(this.mSessionTokenHandle, this.mApplicationPath, this.CommandLine, IntPtr.Zero, IntPtr.Zero, 0, creationFlags, envBlock, this.WorkingDirectory, si, pi); ProcessWaitHandle waitable = new ProcessWaitHandle(pi.hProcess); if (waitable.WaitOne()) { return pi.dwProcessId; } } catch (Win32Exception) { } finally { DestroyEnvironmentBlock(envBlock); } return -1; }
public ProcessExitMonitor(ProcessHandle processHandle) { _processWaitHandle = new ProcessWaitHandle(processHandle); ThreadPool.RegisterWaitForSingleObject(_processWaitHandle, HandleExited, null, -1, true); }
public bool WaitForExit(TimeSpan timeout) { if (IsInvalid || IsClosed) { return true; } using (var waitHandle = new ProcessWaitHandle(this)) { return waitHandle.WaitOne(timeout); } }
private static unsafe int ExecWaitWithCaptureUnimpersonated(SafeUserTokenHandle userToken, string cmd, string currentDir, TempFileCollection tempFiles, ref string outputName, ref string errorName, string trueCmdLine) { IntSecurity.UnmanagedCode.Demand(); FileStream output; FileStream error; int retValue = 0; if (outputName == null || outputName.Length == 0) { outputName = tempFiles.AddExtension("out"); } if (errorName == null || errorName.Length == 0) { errorName = tempFiles.AddExtension("err"); } // Create the files output = CreateInheritedFile(outputName); error = CreateInheritedFile(errorName); bool success = false; SafeNativeMethods.PROCESS_INFORMATION pi = new SafeNativeMethods.PROCESS_INFORMATION(); SafeProcessHandle procSH = new SafeProcessHandle(); SafeThreadHandle threadSH = new SafeThreadHandle(); SafeUserTokenHandle primaryToken = null; try { // Output the command line... StreamWriter sw = new StreamWriter(output, Encoding.UTF8); sw.Write(currentDir); sw.Write("> "); // 'true' command line is used in case the command line points to // a response file sw.WriteLine(trueCmdLine != null ? trueCmdLine : cmd); sw.WriteLine(); sw.WriteLine(); sw.Flush(); NativeMethods.STARTUPINFO si = new NativeMethods.STARTUPINFO(); si.cb = Marshal.SizeOf(si); #if FEATURE_PAL si.dwFlags = NativeMethods.STARTF_USESTDHANDLES; #else //!FEATURE_PAL si.dwFlags = NativeMethods.STARTF_USESTDHANDLES | NativeMethods.STARTF_USESHOWWINDOW; si.wShowWindow = NativeMethods.SW_HIDE; #endif //!FEATURE_PAL si.hStdOutput = output.SafeFileHandle; si.hStdError = error.SafeFileHandle; si.hStdInput = new SafeFileHandle(UnsafeNativeMethods.GetStdHandle(NativeMethods.STD_INPUT_HANDLE), false); // // Prepare the environment // #if PLATFORM_UNIX StringDictionary environment = new CaseSensitiveStringDictionary(); #else StringDictionary environment = new StringDictionary(); #endif // PLATFORM_UNIX // Add the current environment foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables()) { environment[(string)entry.Key] = (string)entry.Value; } // Add the flag to indicate restricted security in the process environment["_ClrRestrictSecAttributes"] = "1"; #if DEBUG environment["OANOCACHE"] = "1"; #endif // set up the environment block parameter byte[] environmentBytes = EnvironmentBlock.ToByteArray(environment, false); fixed(byte *environmentBytesPtr = environmentBytes) { IntPtr environmentPtr = new IntPtr((void *)environmentBytesPtr); if (userToken == null || userToken.IsInvalid) { RuntimeHelpers.PrepareConstrainedRegions(); try {} finally { success = NativeMethods.CreateProcess( null, // String lpApplicationName, new StringBuilder(cmd), // String lpCommandLine, null, // SECURITY_ATTRIBUTES lpProcessAttributes, null, // SECURITY_ATTRIBUTES lpThreadAttributes, true, // bool bInheritHandles, 0, // int dwCreationFlags, environmentPtr, // IntPtr lpEnvironment, currentDir, // String lpCurrentDirectory, si, // STARTUPINFO lpStartupInfo, pi); // PROCESS_INFORMATION lpProcessInformation); if (pi.hProcess != (IntPtr)0 && pi.hProcess != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE) { procSH.InitialSetHandle(pi.hProcess); } if (pi.hThread != (IntPtr)0 && pi.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE) { threadSH.InitialSetHandle(pi.hThread); } } } else { #if FEATURE_PAL throw new NotSupportedException(); #else success = SafeUserTokenHandle.DuplicateTokenEx( userToken, NativeMethods.TOKEN_ALL_ACCESS, null, NativeMethods.IMPERSONATION_LEVEL_SecurityImpersonation, NativeMethods.TOKEN_TYPE_TokenPrimary, out primaryToken ); if (success) { RuntimeHelpers.PrepareConstrainedRegions(); try {} finally { success = NativeMethods.CreateProcessAsUser( primaryToken, // int token, null, // String lpApplicationName, cmd, // String lpCommandLine, null, // SECURITY_ATTRIBUTES lpProcessAttributes, null, // SECURITY_ATTRIBUTES lpThreadAttributes, true, // bool bInheritHandles, 0, // int dwCreationFlags, new HandleRef(null, environmentPtr), // IntPtr lpEnvironment, currentDir, // String lpCurrentDirectory, si, // STARTUPINFO lpStartupInfo, pi); // PROCESS_INFORMATION lpProcessInformation); if (pi.hProcess != (IntPtr)0 && pi.hProcess != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE) { procSH.InitialSetHandle(pi.hProcess); } if (pi.hThread != (IntPtr)0 && pi.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE) { threadSH.InitialSetHandle(pi.hThread); } } } #endif // !FEATURE_PAL } } } finally { // Close the file handles if (!success && (primaryToken != null && !primaryToken.IsInvalid)) { primaryToken.Close(); primaryToken = null; } output.Close(); error.Close(); } if (success) { try { bool signaled; ProcessWaitHandle pwh = null; try { pwh = new ProcessWaitHandle(procSH); signaled = pwh.WaitOne(ProcessTimeOut, false); } finally { if (pwh != null) { pwh.Close(); } } // Check for timeout if (!signaled) { throw new ExternalException(SR.GetString(SR.ExecTimeout, cmd), NativeMethods.WAIT_TIMEOUT); } // Check the process's exit code int status = NativeMethods.STILL_ACTIVE; if (!NativeMethods.GetExitCodeProcess(procSH, out status)) { throw new ExternalException(SR.GetString(SR.ExecCantGetRetCode, cmd), Marshal.GetLastWin32Error()); } retValue = status; } finally { procSH.Close(); threadSH.Close(); if (primaryToken != null && !primaryToken.IsInvalid) { primaryToken.Close(); } } } else { int err = Marshal.GetLastWin32Error(); if (err == NativeMethods.ERROR_NOT_ENOUGH_MEMORY) { throw new OutOfMemoryException(); } Win32Exception win32Exception = new Win32Exception(err); ExternalException ex = new ExternalException(SR.GetString(SR.ExecCantExec, cmd), win32Exception); throw ex; } return(retValue); }
// ************************************************************************ /// <summary> /// Only support existing exectuable (no association or dos command which have no executable like 'dir'). /// But accept full path, partial path or no path where it will use regular system/user path. /// </summary> /// <param name="executablePath"></param> /// <param name="arguments"></param> /// <param name="timeout"></param> /// <returns></returns> private ProcessWithOutputCaptureResult Execute(string executablePath, string arguments = null, int timeout = Timeout.Infinite) { ProcessWithOutputCaptureResult processWithOutputCaptureResult = null; using (Process process = new Process()) { process.StartInfo.FileName = executablePath; process.StartInfo.Arguments = arguments; process.StartInfo.UseShellExecute = false; // required to redirect output to appropriate (output or error) process stream process.StartInfo.WindowStyle = ProcessWindowStyle; process.StartInfo.CreateNoWindow = CreateWindow; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; _outputWaitHandle = new AutoResetEvent(false); _errorWaitHandle = new AutoResetEvent(false); bool asyncReadStarted = false; try { process.OutputDataReceived += ProcessOnOutputDataReceived; process.ErrorDataReceived += ProcessOnErrorDataReceived; process.Start(); // Here there is a race condition. See: https://connect.microsoft.com/VisualStudio/feedback/details/3119134/race-condition-in-process-asynchronous-output-stream-read process.BeginOutputReadLine(); process.BeginErrorReadLine(); asyncReadStarted = true; // See: ProcessStartInfo.RedirectStandardOutput Property: // https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(System.Diagnostics.ProcessStartInfo.RedirectStandardOutput);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5.2);k(DevLang-csharp)&rd=true // All 4 next lines should only be called when not using asynchronous read (process.BeginOutputReadLine() and process.BeginErrorReadLine()) //_sbOutput.AppendLine(process.StandardOutput.ReadToEnd()); //_sbError.AppendLine(process.StandardError.ReadToEnd()); //_sbOutput.AppendLine(process.StandardOutput.ReadToEnd()); //_sbError.AppendLine(process.StandardError.ReadToEnd()); var waitHandles = new WaitHandle[1 + (AdditionalConditionToStopWaitingProcess == null ? 0 : 1)]; waitHandles[0] = new ProcessWaitHandle(process); if (AdditionalConditionToStopWaitingProcess != null) { waitHandles[1] = AdditionalConditionToStopWaitingProcess; } bool hasSucceded = false; int waitResult = WaitHandle.WaitAny(waitHandles, timeout); if (waitResult == 1) // The wait has been interrrupted by an external event { if (IsAdditionalConditionToStopWaitingProcessShouldAlsoKill) { process.Kill(); } } else if (waitResult == 0) // Process has completed normally, no timeout or external event { // Ensure internal process code has completed like ensure to wait until stdout et stderr had been fully completed hasSucceded = process.WaitForExit(timeout); if (_outputWaitHandle.WaitOne(timeout) && _errorWaitHandle.WaitOne(timeout)) { processWithOutputCaptureResult = new ProcessWithOutputCaptureResult(); processWithOutputCaptureResult.ExitCode = process.ExitCode; processWithOutputCaptureResult.Output = _sbOutput.ToString(); processWithOutputCaptureResult.Error = _sbError.ToString(); } } else // Process timeout { processWithOutputCaptureResult = new ProcessWithOutputCaptureResult(); processWithOutputCaptureResult.HasTimeout = true; } } catch (Exception ex) { if (ex.HResult == -2147467259) { processWithOutputCaptureResult = new ProcessWithOutputCaptureResult(); processWithOutputCaptureResult.Exception = new FileNotFoundException("File not found: " + executablePath, ex); } else { processWithOutputCaptureResult = new ProcessWithOutputCaptureResult(); processWithOutputCaptureResult.Exception = ex; } } finally { if (asyncReadStarted) { process.CancelOutputRead(); process.CancelErrorRead(); } process.OutputDataReceived -= ProcessOnOutputDataReceived; process.ErrorDataReceived -= ProcessOnOutputDataReceived; _outputWaitHandle.Close(); _outputWaitHandle.Dispose(); _errorWaitHandle.Close(); _errorWaitHandle.Dispose(); } } return(processWithOutputCaptureResult); }
} // proc CreateProcessPipe public bool StartProcess() { try { if (IsProcessRunning) { StopProcess(); } Log.LogMsg(LogMsgType.Information, "Starte anwendung..."); if (inputEncoding != null) { Console.InputEncoding = inputEncoding; } SafeFileHandle hInput = null; SafeFileHandle hOutput = null; SafeFileHandle hError = null; var hEnvironment = default(GCHandle); using (var startupInfo = new NativeMethods.STARTUPINFO()) try { // Erzeuge die Befehlszeile var sbCommand = new StringBuilder(); var fileName = Config.GetAttribute("filename", String.Empty); if (!String.IsNullOrEmpty(fileName)) { if (fileName.Length > 0 && fileName[0] == '"' && fileName[fileName.Length] == '"') { sbCommand.Append(fileName); } else { sbCommand.Append('"').Append(fileName).Append('"'); } } string sArguments = Config.GetAttribute("arguments", String.Empty); if (!String.IsNullOrEmpty(sArguments)) { sbCommand.Append(' ').Append(sArguments); } XElement arguments = Config.Element(xnArguments); if (arguments != null && !String.IsNullOrEmpty(arguments.Value)) { sbCommand.Append(' ').Append(arguments.Value); } if (sbCommand.Length == 0) { throw new ArgumentException("filename", "Keine Datei angegeben."); } // Working-Directory var workingDirectory = Config.GetAttribute("workingDirectory", null); // Soll der Prozess unter einem anderen Nutzer ausgeführt werden var domain = Config.GetAttribute("domain", null); var userName = Config.GetAttribute("username", null); var password = Config.GetAttribute("password", null); if (!String.IsNullOrEmpty(userName)) { if (!NativeMethods.LogonUser(userName, domain, password, Environment.UserInteractive ? NativeMethods.LOGON_TYPE.LOGON32_LOGON_INTERACTIVE : NativeMethods.LOGON_TYPE.LOGON32_LOGON_SERVICE, NativeMethods.LOGON_PROVIDER.LOGON32_PROVIDER_DEFAULT, out hUser)) { throw new Win32Exception(); } } // Erzeuge eine Environment für den Prozess hEnvironment = GCHandle.Alloc(CreateEnvironment(hUser, userName, Config.GetAttribute("loadUserProfile", false)), GCHandleType.Pinned); // Flags für den neuen Prozess var flags = NativeMethods.CREATE_PROCESS_FLAGS.CREATE_NEW_PROCESS_GROUP | NativeMethods.CREATE_PROCESS_FLAGS.CREATE_NO_WINDOW | NativeMethods.CREATE_PROCESS_FLAGS.CREATE_UNICODE_ENVIRONMENT | NativeMethods.CREATE_PROCESS_FLAGS.CREATE_SUSPENDED; // Erzeuge die Startparameter startupInfo.dwFlags = 0x00000100; CreateProcessPipe(true, out hInput, out startupInfo.hStdInput); CreateProcessPipe(false, out hOutput, out startupInfo.hStdOutput); CreateProcessPipe(false, out hError, out startupInfo.hStdError); NativeMethods.PROCESS_INFORMATION processinformation = new NativeMethods.PROCESS_INFORMATION(); try { if (hUser == IntPtr.Zero) { if (!NativeMethods.CreateProcess(null, sbCommand, null, null, true, flags, hEnvironment.AddrOfPinnedObject(), workingDirectory, startupInfo, processinformation)) { throw new Win32Exception(); } } else { if (!NativeMethods.CreateProcessAsUser(hUser, null, sbCommand, null, null, true, flags, hEnvironment.AddrOfPinnedObject(), workingDirectory, startupInfo, processinformation)) { throw new Win32Exception(); } } // Erzeuge das .net Prozess-Objekt process = Process.GetProcessById(processinformation.dwProcessId); // Erzeuge die Pipes inputStream = new StreamWriter(new FileStream(hInput, FileAccess.Write, 4096, false), inputEncoding ?? Console.InputEncoding); inputStream.AutoFlush = true; outputStream = new StreamReader(new FileStream(hOutput, FileAccess.Read, 4096, false), outputEncoding ?? Console.OutputEncoding); errorStream = new StreamReader(new FileStream(hError, FileAccess.Read, 4096, false), outputEncoding ?? Console.OutputEncoding); exitWaitHandle = new ProcessWaitHandle(processinformation.hProcess); waitHandle = ThreadPool.RegisterWaitForSingleObject(exitWaitHandle, ProcessExited, process, -1, true); arOutputStream = procProcessLogLine.BeginInvoke(LogMsgType.Information, outputStream, null, outputStream); arErrorStream = procProcessLogLine.BeginInvoke(LogMsgType.Warning, errorStream, null, errorStream); // Starte die Anwendung NativeMethods.ResumeThread(processinformation.hThread); } finally { NativeMethods.CloseHandle(processinformation.hThread); } } catch { if (hUser != IntPtr.Zero) { NativeMethods.CloseHandle(hUser); } if (hInput != null && !hInput.IsInvalid) { hInput.Close(); } if (hOutput != null && !hOutput.IsInvalid) { hOutput.Close(); } if (hError != null && !hError.IsInvalid) { hError.Close(); } throw; } finally { if (hEnvironment.IsAllocated) { hEnvironment.Free(); } } CallMemberDirect("ProcessStarted", new object[] { process }, throwExceptions: false); HttpRefreshProperties(); return(true); } catch (Exception e) { Log.LogMsg(LogMsgType.Error, e.GetMessageString()); return(false); } } // proc StartProcess
private void MonitorThread() { ProcessWaitHandle procWaitHandle = null; WaitHandle[] waitHandles; try { unsafe { // Get pointers to shared memory objects. ConsoleParams* consoleParams = (ConsoleParams*)_consoleParams.Get(); CONSOLE_SCREEN_BUFFER_INFO* consoleScreenInfo = (CONSOLE_SCREEN_BUFFER_INFO*) _consoleScreenInfo.Get(); ConsoleBufferInfo* consoleBufferInfo = (ConsoleBufferInfo*)_consoleBufferInfo.Get(); // Keep waiting for new events until process has exitted or thread is aborted. procWaitHandle = new ProcessWaitHandle(_procSafeWaitHandle); waitHandles = new WaitHandle[] { procWaitHandle, _consoleBufferInfo.RequestEvent }; // Loop until console has exitted. while (WaitHandle.WaitAny(waitHandles) > 0) { // Get current window and buffer size. int columns = consoleScreenInfo->srWindow.Right - consoleScreenInfo->srWindow.Left + 1; int rows = consoleScreenInfo->srWindow.Bottom - consoleScreenInfo->srWindow.Top + 1; int bufferColumns = consoleScreenInfo->dwSize.X; int bufferRows = consoleScreenInfo->dwSize.Y; // Check if window size has changed. if (consoleParams->Columns != columns || consoleParams->Rows != rows) { consoleParams->Columns = columns; consoleParams->Rows = rows; // Raise event, window has been resized. if (ConsoleWindowResized != null) ConsoleWindowResized(this, new EventArgs()); } // Check if buffer size has changed. if ((consoleParams->BufferColumns != 0 && consoleParams->BufferColumns != bufferColumns) || (consoleParams->BufferRows != 0 && consoleParams->BufferRows != bufferRows)) { consoleParams->BufferColumns = bufferColumns; consoleParams->BufferRows = bufferRows; // Raise event, buffer has been resized. if (ConsoleBufferResized != null) ConsoleBufferResized(this, new EventArgs()); } if (consoleBufferInfo->NewDataFound || consoleBufferInfo->CursorPositionChanged) { // Raise event, console has sent new data. if (ConsoleNewData != null) ConsoleNewData(this, new EventArgs()); // Check if new data was found. if (consoleBufferInfo->NewDataFound) { // Raise event, buffer data has changed. if (ConsoleBufferChanged != null) ConsoleBufferChanged(this, new EventArgs()); } // Check if cursor posistion has changed. if (consoleBufferInfo->CursorPositionChanged) { // Raise event, cursor position has changed. if (ConsoleCursorPositionChanged != null) ConsoleCursorPositionChanged(this, new EventArgs()); } } } } } catch (ThreadAbortException) { } finally { if (procWaitHandle != null) procWaitHandle.Close(); // Raise event. if (ConsoleClosed != null) ConsoleClosed(this, new EventArgs()); } }
private static unsafe int ExecWaitWithCaptureUnimpersonated(SafeUserTokenHandle userToken, string cmd, string currentDir, TempFileCollection tempFiles, ref string outputName, ref string errorName, string trueCmdLine) { IntSecurity.UnmanagedCode.Demand(); if ((outputName == null) || (outputName.Length == 0)) { outputName = tempFiles.AddExtension("out"); } if ((errorName == null) || (errorName.Length == 0)) { errorName = tempFiles.AddExtension("err"); } FileStream stream = CreateInheritedFile(outputName); FileStream stream2 = CreateInheritedFile(errorName); bool flag = false; Microsoft.Win32.SafeNativeMethods.PROCESS_INFORMATION lpProcessInformation = new Microsoft.Win32.SafeNativeMethods.PROCESS_INFORMATION(); Microsoft.Win32.SafeHandles.SafeProcessHandle processHandle = new Microsoft.Win32.SafeHandles.SafeProcessHandle(); Microsoft.Win32.SafeHandles.SafeThreadHandle handle2 = new Microsoft.Win32.SafeHandles.SafeThreadHandle(); SafeUserTokenHandle hNewToken = null; try { Microsoft.Win32.NativeMethods.STARTUPINFO startupinfo; StreamWriter writer = new StreamWriter(stream, Encoding.UTF8); writer.Write(currentDir); writer.Write("> "); writer.WriteLine((trueCmdLine != null) ? trueCmdLine : cmd); writer.WriteLine(); writer.WriteLine(); writer.Flush(); startupinfo = new Microsoft.Win32.NativeMethods.STARTUPINFO { cb = Marshal.SizeOf(startupinfo), dwFlags = 0x101, wShowWindow = 0, hStdOutput = stream.SafeFileHandle, hStdError = stream2.SafeFileHandle, hStdInput = new SafeFileHandle(Microsoft.Win32.UnsafeNativeMethods.GetStdHandle(-10), false) }; StringDictionary sd = new StringDictionary(); foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables()) { sd[(string)entry.Key] = (string)entry.Value; } sd["_ClrRestrictSecAttributes"] = "1"; byte[] buffer = EnvironmentBlock.ToByteArray(sd, false); try { fixed(byte *numRef = buffer) { IntPtr lpEnvironment = new IntPtr((void *)numRef); if ((userToken == null) || userToken.IsInvalid) { RuntimeHelpers.PrepareConstrainedRegions(); try { goto Label_0325; } finally { flag = Microsoft.Win32.NativeMethods.CreateProcess(null, new StringBuilder(cmd), null, null, true, 0, lpEnvironment, currentDir, startupinfo, lpProcessInformation); if ((lpProcessInformation.hProcess != IntPtr.Zero) && (lpProcessInformation.hProcess != Microsoft.Win32.NativeMethods.INVALID_HANDLE_VALUE)) { processHandle.InitialSetHandle(lpProcessInformation.hProcess); } if ((lpProcessInformation.hThread != IntPtr.Zero) && (lpProcessInformation.hThread != Microsoft.Win32.NativeMethods.INVALID_HANDLE_VALUE)) { handle2.InitialSetHandle(lpProcessInformation.hThread); } } } flag = SafeUserTokenHandle.DuplicateTokenEx(userToken, 0xf01ff, null, 2, 1, out hNewToken); if (flag) { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { flag = Microsoft.Win32.NativeMethods.CreateProcessAsUser(hNewToken, null, cmd, null, null, true, 0, new HandleRef(null, lpEnvironment), currentDir, startupinfo, lpProcessInformation); if ((lpProcessInformation.hProcess != IntPtr.Zero) && (lpProcessInformation.hProcess != Microsoft.Win32.NativeMethods.INVALID_HANDLE_VALUE)) { processHandle.InitialSetHandle(lpProcessInformation.hProcess); } if ((lpProcessInformation.hThread != IntPtr.Zero) && (lpProcessInformation.hThread != Microsoft.Win32.NativeMethods.INVALID_HANDLE_VALUE)) { handle2.InitialSetHandle(lpProcessInformation.hThread); } } } } } finally { numRef = null; } } finally { if ((!flag && (hNewToken != null)) && !hNewToken.IsInvalid) { hNewToken.Close(); hNewToken = null; } stream.Close(); stream2.Close(); } Label_0325: if (flag) { try { bool flag2; ProcessWaitHandle handle4 = null; try { handle4 = new ProcessWaitHandle(processHandle); flag2 = handle4.WaitOne(0x927c0, false); } finally { if (handle4 != null) { handle4.Close(); } } if (!flag2) { throw new ExternalException(SR.GetString("ExecTimeout", new object[] { cmd }), 0x102); } int exitCode = 0x103; if (!Microsoft.Win32.NativeMethods.GetExitCodeProcess(processHandle, out exitCode)) { throw new ExternalException(SR.GetString("ExecCantGetRetCode", new object[] { cmd }), Marshal.GetLastWin32Error()); } return(exitCode); } finally { processHandle.Close(); handle2.Close(); if ((hNewToken != null) && !hNewToken.IsInvalid) { hNewToken.Close(); } } } int error = Marshal.GetLastWin32Error(); if (error == 8) { throw new OutOfMemoryException(); } Win32Exception inner = new Win32Exception(error); ExternalException exception2 = new ExternalException(SR.GetString("ExecCantExec", new object[] { cmd }), inner); throw exception2; }
private static void StartProcessAsUser(ProcessStartInfo psi) { string username = psi.UserName; string domain = psi.Domain; SecureString password = psi.Password; string commandLinePath = "\"" + psi.FileName + "\" " + psi.Arguments; string cwd = psi.WorkingDirectory; IntPtr Token = IntPtr.Zero; IntPtr DupedToken = IntPtr.Zero; SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES(); sa.bInheritHandle = false; sa.Length = Marshal.SizeOf(sa); sa.lpSecurityDescriptor = IntPtr.Zero; if (string.IsNullOrEmpty(domain)) { domain = "."; } IntPtr passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(password ?? new SecureString()); try { if (!LogonUser(username, domain, passwordPtr, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref Token)) { var ex = new Win32Exception(); CloseHandle(Token); throw ex; } } finally { Marshal.ZeroFreeGlobalAllocUnicode(passwordPtr); } const uint GENERIC_ALL = 0x10000000; const int SecurityImpersonation = 2; const int TokenType = 1; PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); try { if (!DuplicateTokenEx(Token, GENERIC_ALL, ref sa, SecurityImpersonation, TokenType, ref DupedToken)) { throw new Win32Exception(); } STARTUPINFO si = new STARTUPINFO(); si.cb = Marshal.SizeOf(si); if (!CreateProcessAsUser(DupedToken, null, commandLinePath, ref sa, ref sa, false, 0, (IntPtr)0, cwd, ref si, out pi)) { throw new Win32Exception(); } uint exitCode = 0; bool timeout = false; ProcessWaitHandle waitable = new ProcessWaitHandle(pi.hProcess); if (!waitable.WaitOne(timeoutToKill * 1000)) { timeout = true; using (Process process = Process.GetProcessById((int)pi.dwProcessId)) if (process != null) { process.Kill(); } } else { if (!GetExitCodeProcess(pi.hProcess, out exitCode)) { throw new Win32Exception(); } } ValidateExitCode(timeout ? -10 : (int)exitCode); } finally { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); CloseHandle(DupedToken); CloseHandle(Token); } }