private static extern bool CreateProcessWithTokenW( IntPtr hToken, LogonFlags dwLogonFlags, [MarshalAs(UnmanagedType.LPTStr)] string lpApplicationName, StringBuilder lpCommandLine, CreationFlags dwCreationFlags, IntPtr lpEnvironment, [MarshalAs(UnmanagedType.LPTStr)] string lpCurrentDirectory, STARTUPINFOEX lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
public static CommandResult RunAsUser(string username, string password, string lpCommandLine, string lpCurrentDirectory, string stdinInput, LogonFlags logonFlags, LogonType logonType) { SecurityIdentifier account = null; if (logonType != LogonType.LOGON32_LOGON_NEW_CREDENTIALS) { account = GetBecomeSid(username); } STARTUPINFOEX si = new STARTUPINFOEX(); si.startupInfo.dwFlags = (int)StartupInfoFlags.USESTDHANDLES; SECURITY_ATTRIBUTES pipesec = new SECURITY_ATTRIBUTES(); pipesec.bInheritHandle = true; // Create the stdout, stderr and stdin pipes used in the process and add to the startupInfo SafeFileHandle stdout_read, stdout_write, stderr_read, stderr_write, stdin_read, stdin_write; if (!CreatePipe(out stdout_read, out stdout_write, pipesec, 0)) { throw new Win32Exception("STDOUT pipe setup failed"); } if (!SetHandleInformation(stdout_read, HandleFlags.INHERIT, 0)) { throw new Win32Exception("STDOUT pipe handle setup failed"); } if (!CreatePipe(out stderr_read, out stderr_write, pipesec, 0)) { throw new Win32Exception("STDERR pipe setup failed"); } if (!SetHandleInformation(stderr_read, HandleFlags.INHERIT, 0)) { throw new Win32Exception("STDERR pipe handle setup failed"); } if (!CreatePipe(out stdin_read, out stdin_write, pipesec, 0)) { throw new Win32Exception("STDIN pipe setup failed"); } if (!SetHandleInformation(stdin_write, HandleFlags.INHERIT, 0)) { throw new Win32Exception("STDIN pipe handle setup failed"); } si.startupInfo.hStdOutput = stdout_write; si.startupInfo.hStdError = stderr_write; si.startupInfo.hStdInput = stdin_read; // Setup the stdin buffer UTF8Encoding utf8_encoding = new UTF8Encoding(false); FileStream stdin_fs = new FileStream(stdin_write, FileAccess.Write, 32768); StreamWriter stdin = new StreamWriter(stdin_fs, utf8_encoding, 32768); // Create the environment block if set IntPtr lpEnvironment = IntPtr.Zero; CreationFlags startup_flags = CreationFlags.CREATE_UNICODE_ENVIRONMENT; PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); // Get the user tokens to try running processes with List <IntPtr> tokens = GetUserTokens(account, username, password, logonType); bool launch_success = false; foreach (IntPtr token in tokens) { if (CreateProcessWithTokenW( token, logonFlags, null, new StringBuilder(lpCommandLine), startup_flags, lpEnvironment, lpCurrentDirectory, si, out pi)) { launch_success = true; break; } } if (!launch_success) { throw new Win32Exception("Failed to start become process"); } CommandResult result = new CommandResult(); // Setup the output buffers and get stdout/stderr FileStream stdout_fs = new FileStream(stdout_read, FileAccess.Read, 4096); StreamReader stdout = new StreamReader(stdout_fs, utf8_encoding, true, 4096); stdout_write.Close(); FileStream stderr_fs = new FileStream(stderr_read, FileAccess.Read, 4096); StreamReader stderr = new StreamReader(stderr_fs, utf8_encoding, true, 4096); stderr_write.Close(); stdin.WriteLine(stdinInput); stdin.Close(); string stdout_str, stderr_str = null; GetProcessOutput(stdout, stderr, out stdout_str, out stderr_str); UInt32 rc = GetProcessExitCode(pi.hProcess); result.StandardOut = stdout_str; result.StandardError = stderr_str; result.ExitCode = rc; return(result); }