public void ExecuteApplication(PasswordEntryManager entryManager) { ExecutionSettings settings = entryManager.GetExecutionSettings(); // Determine the values to use on native calls based on the impersonation settings. string domain = settings.Domain; string username = settings.Username; Win32.LogonFlags logonFlags = settings.NetOnly ? Win32.LogonFlags.LOGON_NETCREDENTIALS_ONLY : Win32.LogonFlags.LOGON_WITH_PROFILE; string application = settings.Application; string arguments = settings.Arguments; string workingDir = string.IsNullOrWhiteSpace(settings.WorkingDir) ? null : settings.WorkingDir; // Create variables required for impersonation handling. IntPtr token = IntPtr.Zero; Win32.StartupInfo startupInfo = new Win32.StartupInfo(); Win32.ProcessInformation processInfo = new Win32.ProcessInformation(); try { // Create process startupInfo.cb = Marshal.SizeOf(startupInfo); bool result = Win32.CreateProcessWithLogonW( username, domain, entryManager.ProcessReplacementTags(settings.Password), (uint)logonFlags, application, arguments, 0, IntPtr.Zero, workingDir, ref startupInfo, out processInfo); if (!result) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } catch (Win32Exception ex) { string errorMessage = ex.Message; if ("A logon request contained an invalid logon type value".Equals(errorMessage)) { errorMessage = string.Concat(errorMessage, ". This is usually caused by attempting to use credentials for the network only but not specifying a domain."); } throw new ApplicationExecutionException(errorMessage, ex); } finally { if (processInfo.process != IntPtr.Zero) { Win32.CloseHandle(processInfo.process); } if (processInfo.thread != IntPtr.Zero) { Win32.CloseHandle(processInfo.thread); } } }
void StartProcess() { IntPtr stdin = IntPtr.Zero; IntPtr stdoutRead = IntPtr.Zero; IntPtr stdoutWrite = IntPtr.Zero; IntPtr stderr = IntPtr.Zero; try { Win32.StartupInfo startupInfo = new Win32.StartupInfo(); startupInfo.Initialize(); startupInfo.Flags = Win32.StartProcessFlags.UseStdHandles; #region Set stdin { if (RedirectedStandardInput != null) { stdin = RedirectedStandardInput.ReleaseStandardOutputReadHandle(); Helper.EnsureHandleInheritable(stdin); } else { /* Duplicate the handle so that * the cleaning logic is unified. */ stdin = Helper.DuplicateHandleForInheritance( Win32.GetStdHandle(Win32.StandardHandleId.StandardInput)); } startupInfo.StandardInput = stdin; } #endregion Set stdin #region Set stdout { Win32.SecurityAttributes pipeAttributes = new Win32.SecurityAttributes(); pipeAttributes.Initialize(); if (Win32.CreatePipe(out stdoutRead, out stdoutWrite, ref pipeAttributes, 4096) == Win32.Bool.False) { stdoutRead = IntPtr.Zero; stdoutWrite = IntPtr.Zero; int lastError = Marshal.GetLastWin32Error(); throw new Win32Exception(lastError, string.Format(CouldNotCreatePipeErrorFormat, lastError)); } Helper.EnsureHandleInheritable(stdoutWrite); startupInfo.StandardOutput = stdoutWrite; } #endregion Set stdout #region Set stderr { if (RedirectedStandardError != null) { stderr = standardErrorAppend ? Helper.OpenAppendFile(RedirectedStandardError) : Helper.OpenTruncatedFile(RedirectedStandardError); Helper.EnsureHandleInheritable(stderr); } else { stderr = Helper.DuplicateHandleForInheritance( Win32.GetStdHandle(Win32.StandardHandleId.StandardError)); } startupInfo.StandardError = stderr; } #endregion Set stderr Win32.ProcessInformation processInformation; /* Create the process suspended, * and resume it only after we * have started waiting for it. */ if (Win32.CreateProcess(null, BuildCommandLine(), IntPtr.Zero, IntPtr.Zero, Win32.Bool.True, Win32.ProcessCreationFlags.CreateSuspended, IntPtr.Zero, InitialWorkingDirectory, ref startupInfo, out processInformation) == Win32.Bool.False) { int lastError = Marshal.GetLastWin32Error(); throw new Win32Exception(lastError, string.Format(CouldNotCreateProcessErrorFormat, lastError)); } hasExited = false; processHandle = processInformation.HandleToProcess; ProcessId = processInformation.ProcessId; new Thread(WaitForProcessExitWorker).Start(this); Win32.ResumeThread(processInformation.HandleToThread); Win32.CloseHandle(processInformation.HandleToThread); stdoutReadHandle = stdoutRead; /* Prevent this very handle from being * closed. Other handles are useless now * and will be closed in "finally". */ stdoutRead = IntPtr.Zero; } finally { if (stdin != IntPtr.Zero) { Win32.CloseHandle(stdin); } if (stdoutRead != IntPtr.Zero) { Win32.CloseHandle(stdoutRead); } if (stdoutWrite != IntPtr.Zero) { Win32.CloseHandle(stdoutWrite); } if (stderr != IntPtr.Zero) { Win32.CloseHandle(stderr); } } }