public void Run() { IntPtr primaryToken = GetCurrentUserToken(); if (primaryToken == IntPtr.Zero) { return; } NativeMethods.STARTUPINFO StartupInfo = new NativeMethods.STARTUPINFO(); processInfo_ = new NativeMethods.PROCESS_INFORMATION(); StartupInfo.cb = Marshal.SizeOf(StartupInfo); NativeMethods.SECURITY_ATTRIBUTES Security1 = new NativeMethods.SECURITY_ATTRIBUTES(); NativeMethods.SECURITY_ATTRIBUTES Security2 = new NativeMethods.SECURITY_ATTRIBUTES(); string command = "\"" + processPath_ + "\""; if ((arguments_ != null) && (arguments_.Length != 0)) { command += " " + arguments_; } IntPtr lpEnvironment = IntPtr.Zero; bool resultEnv = NativeMethods.CreateEnvironmentBlock(out lpEnvironment, primaryToken, false); if (resultEnv != true) { int nError = NativeMethods.GetLastError(); } NativeMethods.CreateProcessAsUser(primaryToken, null, command, ref Security1, ref Security2, false, NativeMethods.CREATE_NO_WINDOW | NativeMethods.NORMAL_PRIORITY_CLASS | NativeMethods.CREATE_UNICODE_ENVIRONMENT, lpEnvironment, null, ref StartupInfo, out processInfo_); NativeMethods.DestroyEnvironmentBlock(lpEnvironment); NativeMethods.CloseHandle(primaryToken); }
private Win32Process(NativeMethods.PROCESS_INFORMATION pi, StreamWriter stdin, StreamReader stdout, StreamReader stderror) { StandardInput = stdin; StandardOutput = stdout; StandardError = stderror; _hasExited = false; _exitCodeLock = new object(); Id = pi.dwProcessId; MainThreadId = pi.dwThreadId; _processHandle = new SafeProcessHandle(pi.hProcess, true); var threadHandle = new SafeThreadHandle(pi.hThread); var wait = new ProcessWaitHandle(_processHandle); _registeredWait = ThreadPool.RegisterWaitForSingleObject(wait, (o, t) => { _registeredWait.Unregister(wait); SetExitState(); Exited?.Invoke(this, EventArgs.Empty); _processHandle.Close(); threadHandle.Close(); wait.Close(); }, null, -1, true); _disposable .Add(() => _registeredWait.Unregister(wait)) .Add(_processHandle) .Add(threadHandle) .Add(wait); }
public Process Execute(string fileName, string arguments, string currentDirectory, bool interactive, Dictionary <string, string> extraEnvironmentVariables, PipeStream stdinPipeName, PipeStream stdoutPipeName, PipeStream stderrPipeName) { // C with Win32 API example to start a process under a different user: http://msdn.microsoft.com/en-us/library/aa379608%28VS.85%29.aspx if (!this.prison.IsLocked) { throw new PrisonException("The prison has to be locked before you can use it."); } this.prison.User.Profile.LoadUserProfileIfNotLoaded(); var envs = this.prison.User.RetrieveDefaultEnvironmentVariables(); // environmentVariables from the method parameters have precedence over the default envs if (extraEnvironmentVariables != null) { foreach (var env in extraEnvironmentVariables) { envs[env.Key] = env.Value; } } string envBlock = BuildEnvironmentVariable(envs); Logger.Debug("Starting process '{0}' with arguments '{1}' as user '{2}' in working directory '{3}'", fileName, arguments, this.prison.User.UserName, this.prison.PrisonHomePath); if (string.IsNullOrWhiteSpace(fileName)) { fileName = null; } if (this.prison.RuleEnabled(RuleTypes.WindowStation)) { var winStationCell = this.prison.prisonCells.First((a) => { return(a.RuleType == RuleTypes.WindowStation); }); winStationCell.Apply(this.prison); } NativeMethods.PROCESS_INFORMATION processInfo = this.NativeCreateProcessAsUser(interactive, fileName, arguments, currentDirectory, envBlock, stdinPipeName, stdoutPipeName, stderrPipeName); NativeMethods.CloseHandle(processInfo.hProcess); NativeMethods.CloseHandle(processInfo.hThread); var workerProcessPid = processInfo.dwProcessId; var workerProcess = Process.GetProcessById(workerProcessPid); // Tag the process with the Job Object before resuming the process. this.prison.jobObject.AddProcess(workerProcess); // Add process in the second job object this.prison.PrisonGuard.AddProcessToGuardJobObject(workerProcess); // This would allow the process to query the ExitCode. ref: http://msdn.microsoft.com/en-us/magazine/cc163900.aspx workerProcess.EnableRaisingEvents = true; ResumeProcess(workerProcess); return(workerProcess); }
private static int CreateProcessAsUser(string executablePath, string commandLine, string workingDirectory, IntPtr userToken) { using (AutoDisposeHandle environmentVariables = CreateEnvironmentBlock(userToken)) { if (environmentVariables == null) { return(-1); } NativeMethods.STARTUPINFO startupInformation = new NativeMethods.STARTUPINFO(); startupInformation.length = Marshal.SizeOf(typeof(NativeMethods.STARTUPINFO)); startupInformation.desktop = "Winsta0\\Default"; startupInformation.showWindow = (short)NativeMethods.WindowShowStyle.ShowNoActivate; NativeMethods.PROCESS_INFORMATION processInformation = new NativeMethods.PROCESS_INFORMATION(); try { bool result = NativeMethods.CreateProcessAsUser ( userToken, executablePath, commandLine, IntPtr.Zero, IntPtr.Zero, false, (uint)(NativeMethods.CreateProcessFlags.DETACHED_PROCESS | NativeMethods.CreateProcessFlags.CREATE_UNICODE_ENVIRONMENT), environmentVariables, workingDirectory, ref startupInformation, ref processInformation ); if (!result) { Win32Helper.ThrowLastWin32Error("Unable to start process \"" + executablePath + "\""); } return(processInformation.processID); } finally { if (processInformation.processHandle != IntPtr.Zero) { try { NativeMethods.CloseHandle(processInformation.processHandle); } catch { } } if (processInformation.threadHandle != IntPtr.Zero) { try { NativeMethods.CloseHandle(processInformation.threadHandle); } catch { } } } } }
/// <summary> /// Initializes a new instance of the BrokerProcess class /// </summary> /// <param name="brokerFileName">indicating the broker file name</param> /// <param name="environments">indicating the environments</param> public BrokerProcess(string brokerFileName, NameValueConfigurationCollection environments) { this.startupInfo = new NativeMethods.STARTUPINFO(); this.startupInfo.cb = Marshal.SizeOf(typeof(NativeMethods.STARTUPINFO)); this.processInfo = new NativeMethods.PROCESS_INFORMATION(); string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string fileName = Path.Combine(path, brokerFileName); StringBuilder commandLine = null; TraceHelper.TraceEvent(TraceEventType.Information, "[BrokerProcess] Start broker process, FileName = {0}", fileName); IntPtr environmentPtr; if (environments != null) { this.environmentHandle = GCHandle.Alloc(ToByteArray(environments), GCHandleType.Pinned); environmentPtr = this.environmentHandle.AddrOfPinnedObject(); } else { environmentPtr = IntPtr.Zero; } if (!NativeMethods.CreateProcess(fileName, commandLine, IntPtr.Zero, IntPtr.Zero, true, creationFlags, environmentPtr, path, ref this.startupInfo, out this.processInfo)) { int errorCode = Marshal.GetLastWin32Error(); TraceHelper.TraceEvent(TraceEventType.Error, "[BrokerProcess] Start broker process failed: {0}", errorCode); ThrowHelper.ThrowSessionFault(SOAFaultCode.Broker_FailedToStartBrokerServiceProcess, SR.FailedToStartBrokerServiceProcess, errorCode.ToString()); } SafeWaitHandle handle = new SafeWaitHandle(this.processInfo.hProcess, false); if (handle.IsClosed || handle.IsInvalid) { TraceHelper.TraceEvent(TraceEventType.Error, "[BrokerProcess] Start broker process failed because the process handle is invalid or closed."); ThrowHelper.ThrowSessionFault(SOAFaultCode.Broker_FailedToStartBrokerServiceProcess, SR.FailedToStartBrokerServiceProcess, "Handle is invalid or closed"); } string uniqueWaitHandleName = BuildUniqueWaitHandle(this.Id, out this.readyWaitHandle); WaitOrTimerCallback brokerProcessReadyCallback = new ThreadHelper <object>(new WaitOrTimerCallback(this.BrokerProcessReadyCallback)).WaitOrTimerCallbackRoot; WaitOrTimerCallback processExitCallback = new ThreadHelper <object>(new WaitOrTimerCallback(this.ProcessExitCallback)).WaitOrTimerCallbackRoot; this.exitWaitHandle = new ManualResetEvent(false); this.exitWaitHandle.SafeWaitHandle = handle; // Register broker process exit callback ThreadPool.RegisterWaitForSingleObject(this.exitWaitHandle, processExitCallback, null, -1, true); // Register callback to be raised when broker process opened service host and is ready to initialize. ThreadPool.RegisterWaitForSingleObject(this.readyWaitHandle, brokerProcessReadyCallback, null, readyTimeout, true); }
/// <summary> /// ユーザーセッションでコマンドを実行する /// </summary> /// <param name="commandline">実行したいコマンド</param> /// <exception cref="InvalidOperationException"></exception> public static void CreateProcessAsUser(string commandline) { var sessionId = NativeMethods.WTSGetActiveConsoleSessionId(); IntPtr hPToken = IntPtr.Zero; var hUserTokenDup = IntPtr.Zero; var ret = NativeMethods.WTSQueryUserToken(sessionId, out hPToken); var sa = new NativeMethods.SECURITY_ATTRIBUTES(); sa.nLength = Marshal.SizeOf(sa); if (!NativeMethods.DuplicateTokenEx(hPToken, NativeMethods.TOKEN_ALL_ACCESS, ref sa, NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityDelegation, NativeMethods.TOKEN_TYPE.TokenPrimary, out hUserTokenDup)) { NativeMethods.CloseHandle(hPToken); throw new InvalidOperationException(); } var si = new NativeMethods.STARTUPINFO() { cb = Marshal.SizeOf(sa), lpDesktop = @"winsta0\default", wShowWindow = 0,//SW_HIDE dwFlags = NativeMethods.STARTF_USESHOWWINDOW, }; var creationFlags = NativeMethods.CREATE_UNICODE_ENVIRONMENT; var env = IntPtr.Zero; // アクティブユーザのセッションを設定します var ret2 = NativeMethods.SetTokenInformation(hUserTokenDup, NativeMethods.TOKEN_INFORMATION_CLASS.TokenSessionId, ref sessionId, sizeof(NativeMethods.TOKEN_INFORMATION_CLASS)); // 環境変数を設定 if (!NativeMethods.CreateEnvironmentBlock(out env, hUserTokenDup, true)) { env = IntPtr.Zero; } NativeMethods.PROCESS_INFORMATION pi = new NativeMethods.PROCESS_INFORMATION(); NativeMethods.CreateProcessAsUser(hUserTokenDup, IntPtr.Zero, commandline, IntPtr.Zero, IntPtr.Zero, false, creationFlags, env, IntPtr.Zero, ref si, out pi); NativeMethods.DestroyEnvironmentBlock(env); }
private Win32Process(NativeMethods.PROCESS_INFORMATION pi) { _hasExited = false; _exitCodeLock = new object(); ProcessId = pi.dwProcessId; MainThreadId = pi.dwThreadId; _processHandle = new SafeProcessHandle(pi.hProcess, true); _threadHandle = new SafeThreadHandle(pi.hThread); _wait = new ProcessWaitHandle(_processHandle); _registeredWait = ThreadPool.RegisterWaitForSingleObject(_wait, (o, t) => { _registeredWait.Unregister(_wait); SetExitState(); Exited?.Invoke(this, new Win32ProcessExitEventArgs(_exitCode)); _processHandle.Close(); _threadHandle.Close(); _wait.Close(); }, null, -1, true); }
/// <summary> /// If HpcServiceHost is launched to run a pre/post task, launch the pre/post task /// </summary> private static bool RunPrePostTask(ref uint exitCode) { bool prePostTaskExists = false; string prePostTaskCommandLine = Environment.GetEnvironmentVariable(Constant.PrePostTaskCommandLineEnvVar); // Check if pre/post task exists prePostTaskExists = !string.IsNullOrEmpty(prePostTaskCommandLine); // if so run it if (prePostTaskExists) { string serviceWorkingDirectory = null; // Working directory is the service assembly's directory. If we are on Azure, change to the service package's dir. If // not on azure use service assemblies directory from service config which is passed to svchost via env var so we dont // need to read the svc config file again on every CN (which is slow) if (SoaHelper.IsOnAzure()) { serviceWorkingDirectory = Utility.GetServiceLocalCacheFullPath(); } else { serviceWorkingDirectory = Environment.ExpandEnvironmentVariables( Environment.GetEnvironmentVariable(Constant.PrePostTaskOnPremiseWorkingDirEnvVar)); } NativeMethods.STARTUPINFO startupInfo = new NativeMethods.STARTUPINFO(); startupInfo.cb = Marshal.SizeOf(typeof(NativeMethods.STARTUPINFO)); NativeMethods.PROCESS_INFORMATION processInfo = new NativeMethods.PROCESS_INFORMATION(); StringBuilder commandLine = new StringBuilder(); // Run command from comspec (like node manager babysitter) to ensure env vars are expanded and command runs as if launched from node manager commandLine.AppendFormat("\"{0}\" /S /c \"{1}\"", Environment.GetEnvironmentVariable("ComSpec"), prePostTaskCommandLine); TraceHelper.TraceInfo( jobId, "Executing '{0}'", prePostTaskCommandLine); // Start the task bool ret = NativeMethods.CreateProcess(null, commandLine, IntPtr.Zero, IntPtr.Zero, true, NativeMethods.CREATE_UNICODE_ENVIRONMENT, IntPtr.Zero, serviceWorkingDirectory, ref startupInfo, out processInfo); // If CreateProcess succeeded if (ret) { using (SafeWaitHandle processHandle = new SafeWaitHandle(processInfo.hProcess, true)) using (SafeWaitHandle threadHandle = new SafeWaitHandle(processInfo.hThread, true)) { if (processHandle.IsClosed || processHandle.IsInvalid) { TraceHelper.TraceError( jobId, "Process handle is invalid or closed. Task commandline = {0}", commandLine); exitCode = 1; return(true); } // Wait for task to complete NativeMethods.WaitForSingleObject(processInfo.hProcess, Timeout.Infinite); // Trace the results NativeMethods.GetExitCodeProcess(new SafeProcessHandle(processInfo.hProcess, false), out exitCode); TraceHelper.TraceInfo( jobId, "ExitCode = {0}", exitCode); } } else { int errorCode = Marshal.GetLastWin32Error(); TraceHelper.TraceError( jobId, "Cannot start pre/post task: '{0}'. Exit code = {1}", prePostTaskCommandLine, errorCode); exitCode = (uint)errorCode; } } return(prePostTaskExists); }
/// <include file='doc\Executor.uex' path='docs/doc[@for="Executor.ExecWaitWithCapture3"]/*' /> /// <devdoc> /// <para>[To be supplied.]</para> /// </devdoc> internal static int ExecWaitWithCapture(IntPtr userToken, string cmd, string currentDir, TempFileCollection tempFiles, ref string outputName, ref string errorName, string trueCmdLine) { IntSecurity.UnmanagedCode.Demand(); IntPtr output; IntPtr 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; NativeMethods.PROCESS_INFORMATION pi = new NativeMethods.PROCESS_INFORMATION(); IntPtr primaryToken = IntPtr.Zero; GCHandle environmentHandle = new GCHandle(); try { // Output the command line... // Make sure the FileStream doesn't own the handle FileStream outputStream = new FileStream(output, FileAccess.ReadWrite, false /*ownsHandle*/); StreamWriter sw = new StreamWriter(outputStream, 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(); outputStream.Close(); NativeMethods.STARTUPINFO si = new NativeMethods.STARTUPINFO(); si.cb = Marshal.SizeOf(si); si.dwFlags = NativeMethods.STARTF_USESTDHANDLES; si.hStdOutput = output; si.hStdError = error; si.hStdInput = UnsafeNativeMethods.GetStdHandle(NativeMethods.STD_INPUT_HANDLE); // // Prepare the environment // Hashtable environment = new Hashtable(); // Add the current environment foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables()) { environment.Add((string)entry.Key, (string)entry.Value); } // Add the flag to indicate restricted security in the process environment.Add("_ClrRestrictSecAttributes", "1"); // set up the environment block parameter IntPtr environmentPtr = (IntPtr)0; byte[] environmentBytes = EnvironmentToByteArray(environment); environmentHandle = GCHandle.Alloc(environmentBytes, GCHandleType.Pinned); environmentPtr = environmentHandle.AddrOfPinnedObject(); if (userToken == IntPtr.Zero) { success = UnsafeNativeMethods.CreateProcess( null, // String lpApplicationName, new StringBuilder(cmd), // String lpCommandLine, null, // SECURITY_ATTRIBUTES lpProcessAttributes, null, // SECURITY_ATTRIBUTES lpThreadAttributes, true, // bool bInheritHandles, 0, // int dwCreationFlags, environmentPtr, // int lpEnvironment, currentDir, // String lpCurrentDirectory, si, // STARTUPINFO lpStartupInfo, pi); // PROCESS_INFORMATION lpProcessInformation); } else { throw new NotSupportedException(); } } finally { // free environment block if (environmentHandle.IsAllocated) { environmentHandle.Free(); } // Close the file handles UnsafeNativeMethods.CloseHandle(output); UnsafeNativeMethods.CloseHandle(error); } if (success) { try { int ret = SafeNativeMethods.WaitForSingleObject(pi.hProcess, ProcessTimeOut); // Check for timeout if (ret == NativeMethods.WAIT_TIMEOUT) { throw new ExternalException(SR.GetString(SR.ExecTimeout, cmd), NativeMethods.WAIT_TIMEOUT); } if (ret != NativeMethods.WAIT_OBJECT_0) { throw new ExternalException(SR.GetString(SR.ExecBadreturn, cmd), Marshal.GetLastWin32Error()); } // Check the process's exit code int status = NativeMethods.STILL_ACTIVE; if (!UnsafeNativeMethods.GetExitCodeProcess(pi.hProcess, ref status)) { throw new ExternalException(SR.GetString(SR.ExecCantGetRetCode, cmd), Marshal.GetLastWin32Error()); } retValue = status; } finally { UnsafeNativeMethods.CloseHandle(pi.hThread); UnsafeNativeMethods.CloseHandle(pi.hProcess); if (primaryToken != IntPtr.Zero) { UnsafeNativeMethods.CloseHandle(primaryToken); } } } else { throw new ExternalException(SR.GetString(SR.ExecCantExec, cmd), Marshal.GetLastWin32Error()); } return(retValue); }
private bool StartWithCreateProcess(ProcessStartInfo startInfo) { if (startInfo.RedirectStandardInput) { throw new InvalidOperationException("Standard input redirect not allowed"); } if (startInfo.RedirectStandardOutput) { throw new InvalidOperationException("Standard output redirect not allowed"); } if (startInfo.RedirectStandardError) { throw new InvalidOperationException("Standard error redirect not allowed"); } //Cannot start a new process and store its handle if the object has been disposed, since finalization has been suppressed. if (this._Disposed) { throw new ObjectDisposedException(GetType().Name); } StringBuilder commandLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments); NativeMethods.STARTUPINFO startupInfo = new NativeMethods.STARTUPINFO(); NativeMethods.PROCESS_INFORMATION processInfo = new NativeMethods.PROCESS_INFORMATION(); bool retVal; int errorCode = 0; // set up the creation flags paramater int creationFlags = 0; if (startInfo.CreateNoWindow) { creationFlags |= (int)NativeMethods.CreateProcessFlags.CREATE_NO_WINDOW; startupInfo.dwFlags = NativeMethods.STARTF_USESHOWWINDOW; startupInfo.wShowWindow = (short)NativeMethods.SW_HIDE; } else { creationFlags |= (int)NativeMethods.CreateProcessFlags.CREATE_NEW_CONSOLE; switch (startInfo.WindowStyle) { case ProcessWindowStyle.Maximized: startupInfo.dwFlags = NativeMethods.STARTF_USESHOWWINDOW; startupInfo.wShowWindow = (short)NativeMethods.SW_MAXIMIZE; break; case ProcessWindowStyle.Minimized: startupInfo.dwFlags = NativeMethods.STARTF_USESHOWWINDOW; startupInfo.wShowWindow = (short)NativeMethods.SW_MINIMIZE; break; case ProcessWindowStyle.Hidden: startupInfo.dwFlags = NativeMethods.STARTF_USESHOWWINDOW; startupInfo.wShowWindow = (short)NativeMethods.SW_HIDE; break; } } string workingDirectory = startInfo.WorkingDirectory; if (workingDirectory == string.Empty) { workingDirectory = ProcessUtils.StartupPath; } RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { retVal = NativeMethods.CreateProcess( null, // we don't need this since all the info is in commandLine commandLine.ToString(), // pointer to the command line string IntPtr.Zero, // pointer to process security attributes, we don't need to inheriat the handle IntPtr.Zero, // pointer to thread security attributes true, // handle inheritance flag creationFlags, // creation flags IntPtr.Zero, // pointer to new environment block workingDirectory, // pointer to current directory name ref startupInfo, // pointer to STARTUPINFO out processInfo // pointer to PROCESS_INFORMATION ); if (!retVal) { errorCode = Marshal.GetLastWin32Error(); } } if (!retVal) { if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT) { throw new Win32Exception(errorCode, "Invalid application"); } throw new Win32Exception(errorCode); } bool ret = false; if (processInfo.hProcess != (IntPtr)0 && processInfo.hProcess != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE) { _ProcessHandle = processInfo.hProcess; _HaveProcessHandle = true; if (processInfo.hThread != (IntPtr)0 && processInfo.hThread != (IntPtr)NativeMethods.INVALID_HANDLE_VALUE) { NativeMethods.CloseHandle(processInfo.hThread); } ret = true; } return(ret); }
private static void StartProcessWithLogonNetOnly(ProcessStartInfo startInfo, bool waitForExit) { if (startInfo.UseShellExecute) { throw new InvalidOperationException("UseShellExecute must be false."); } if (startInfo.LoadUserProfile) { throw new InvalidOperationException("LoadUserProfile cannot be used."); } if (string.IsNullOrEmpty(startInfo.UserName)) { throw new InvalidOperationException("UserName is empty."); } var cmdLine = BuildCommandLine(startInfo.FileName, startInfo.Arguments); var lpStartupInfo = new NativeMethods.STARTUPINFO(); var lpProcessInformation = new NativeMethods.PROCESS_INFORMATION(); int creationFlags = 0; if (startInfo.CreateNoWindow) { creationFlags |= 0x8000000; } IntPtr zero = IntPtr.Zero; string workingDirectory = startInfo.WorkingDirectory; if (string.IsNullOrEmpty(workingDirectory)) { workingDirectory = Environment.CurrentDirectory; } NativeMethods.LogonFlags logonFlags = NativeMethods.LogonFlags.LOGON_NETCREDENTIALS_ONLY; //NetOnly; IntPtr passwordPrt = IntPtr.Zero; try { if (startInfo.Password == null) { passwordPrt = Marshal.StringToCoTaskMemUni(string.Empty); } else { passwordPrt = Marshal.SecureStringToCoTaskMemUnicode(startInfo.Password); } int error = 0; bool flag = NativeMethods.CreateProcessWithLogonW(startInfo.UserName, startInfo.Domain, passwordPrt, logonFlags, null, cmdLine, creationFlags, zero, workingDirectory, lpStartupInfo, lpProcessInformation); if (!flag) { error = Marshal.GetLastWin32Error(); } if (!flag) { if (error != 0xc1 && error != 0xd8) { throw new Win32Exception(error); } throw new Win32Exception(error, "Invalid Application"); } } finally { if (passwordPrt != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(passwordPrt); } } if (waitForExit) { NativeMethods.WaitForSingleObject(lpProcessInformation.hProcess, 0xFFFFFFFF); } }
public Tuple <bool, int> CreateProcessAsUser(IntPtr hUserToken, string appFileName, string appArgs) { try { // Identify user from access token. WindowsIdentity userId = new WindowsIdentity(hUserToken); _logger.Log("Create process for: " + userId.Name + " [" + appFileName + " " + appArgs + "]."); userId.Dispose(); // Obtain duplicated user token (elevated if UAC is turned on/enabled). IntPtr hDuplicateToken = new WindowsHelper(_logger).DuplicateToken(hUserToken); // Initialize process info and startup info. NativeMethods.PROCESS_INFORMATION pi = new NativeMethods.PROCESS_INFORMATION(); NativeMethods.STARTUPINFO si = new NativeMethods.STARTUPINFO(); si.cb = Marshal.SizeOf(si); si.lpDesktop = "winsta0\\default"; NativeMethods.SECURITY_ATTRIBUTES lpProcessAttributes = new NativeMethods.SECURITY_ATTRIBUTES(); NativeMethods.SECURITY_ATTRIBUTES lpThreadAttributes = new NativeMethods.SECURITY_ATTRIBUTES(); IntPtr hEnvironment = IntPtr.Zero; if (!NativeMethods.CreateEnvironmentBlock(out hEnvironment, hDuplicateToken, true)) { _logger.Log("Unable to create environment block [CreateEnvironmentBlock=" + Marshal.GetLastWin32Error().ToString() + "].", Logger.MsgType.WARN); } if (!NativeMethods.CreateProcessAsUser( hDuplicateToken, null, appFileName + " " + appArgs, ref lpProcessAttributes, ref lpThreadAttributes, false, (uint)NativeMethods.CreateProcessFlags.NORMAL_PRIORITY_CLASS | (uint)NativeMethods.CreateProcessFlags.CREATE_UNICODE_ENVIRONMENT | (uint)NativeMethods.CreateProcessFlags.CREATE_NEW_CONSOLE, hEnvironment, Path.GetDirectoryName(appFileName), ref si, out pi)) { _logger.Log("Unable to create user process [CreateProcessAsUser="******"].", Logger.MsgType.ERROR); Marshal.FreeHGlobal(hDuplicateToken); Marshal.FreeHGlobal(hEnvironment); Marshal.FreeHGlobal(hUserToken); return(new Tuple <bool, int>(false, -1)); } else { _logger.Log("Created new process: " + pi.dwProcessId.ToString() + "/" + appFileName + " " + appArgs); var newProcess = Process.GetProcessById(pi.dwProcessId); try { // For UI apps, wait for idle state, before continuing. newProcess.WaitForInputIdle(2000); } catch (InvalidOperationException) { // Must be a non-UI app, just give it a sec to start. Thread.Sleep(1000); } newProcess.Dispose(); Marshal.FreeHGlobal(hDuplicateToken); Marshal.FreeHGlobal(hEnvironment); Marshal.FreeHGlobal(hUserToken); return(new Tuple <bool, int>(true, pi.dwProcessId)); } } catch (Exception e) { _logger.Log(e, "Failed to create process as user."); return(new Tuple <bool, int>(false, -1)); } }
public bool CreateProcessAsUser(WindowsIdentity userId, string appFileName, string appArgs) { try { _logger.Log("Create process for: " + userId.Name); List <Tuple <uint, string> > userSessions = new WindowsHelper(_logger).GetUserSessions(); int sessionId = -1; foreach (Tuple <uint, string> logonSession in userSessions) { if (logonSession.Item2.ToLower().Equals(userId.Name.ToLower())) { sessionId = (int)logonSession.Item1; break; } } if (sessionId == -1) { _logger.Log("Failed to match any/existing logon session with user [" + userId.Name + "].", Logger.MsgType.ERROR); return(false); } if (!NativeMethods.WTSQueryUserToken((uint)sessionId, out IntPtr hUserToken)) { _logger.Log("Failed to query user token [WTSQueryUserToken=" + Marshal.GetLastWin32Error().ToString() + "].", Logger.MsgType.ERROR); return(false); } // Obtain duplicated user token (elevated if UAC is turned on/enabled). IntPtr hDuplicateToken = new WindowsHelper(_logger).DuplicateToken(hUserToken, (uint)sessionId); Marshal.FreeHGlobal(hUserToken); // Initialize process info and startup info. NativeMethods.PROCESS_INFORMATION pi = new NativeMethods.PROCESS_INFORMATION(); NativeMethods.STARTUPINFO si = new NativeMethods.STARTUPINFO(); si.cb = Marshal.SizeOf(si); si.lpDesktop = "winsta0\\default"; NativeMethods.SECURITY_ATTRIBUTES lpProcessAttributes = new NativeMethods.SECURITY_ATTRIBUTES(); NativeMethods.SECURITY_ATTRIBUTES lpThreadAttributes = new NativeMethods.SECURITY_ATTRIBUTES(); IntPtr hEnvironment = IntPtr.Zero; if (!NativeMethods.CreateEnvironmentBlock(out hEnvironment, hDuplicateToken, true)) { _logger.Log("Unable to create environment block [CreateEnvironmentBlock=" + Marshal.GetLastWin32Error().ToString() + "].", Logger.MsgType.WARN); } if (!NativeMethods.CreateProcessAsUser( hDuplicateToken, null, appFileName + " " + appArgs, ref lpProcessAttributes, ref lpThreadAttributes, false, (uint)NativeMethods.CreateProcessFlags.NORMAL_PRIORITY_CLASS | (uint)NativeMethods.CreateProcessFlags.CREATE_UNICODE_ENVIRONMENT | (uint)NativeMethods.CreateProcessFlags.CREATE_NEW_CONSOLE, hEnvironment, Path.GetDirectoryName(appFileName), ref si, out pi)) { _logger.Log("ERROR: Unable to create user process [CreateProcessAsUser="******"]."); return(false); } else { _logger.Log("Created new process: " + pi.dwProcessId.ToString() + "/" + appFileName + " " + appArgs); var newProcess = Process.GetProcessById(pi.dwProcessId); try { // For UI apps, wait for idle state, before continuing. newProcess.WaitForInputIdle(2000); } catch (InvalidOperationException) { // Must be a non-UI app, just give it a sec to start. Thread.Sleep(1000); } return(true); } } catch (Exception e) { _logger.Log(e, "Failed to create process as user."); return(false); } }