CreateProcessAsUser函数是一种可以在用户会话中创建新进程的Windows API。它提供了一种安全、可靠的方式,让您的程序可以在已登录的Windows用户账户下执行,并且可以以用户身份运行。本文将介绍。
一、理解CreateProcessAsUser函数
使用CreateProcessAsUser函数可以创建新的进程,并在指定的用户会话中以指定的用户身份运行。这个函数的参数与CreateProcess函数类似,但它还需要两个额外的参数:用户令牌和启动信息。
1. 用户令牌:指定将要在其中运行新进程的用户令牌。该令牌可以是用LogonUser或其它API函数创建的令牌。如果该参数为NULL,则表示将在系统账户下运行新进程。
2. 启动信息:指定一个STARTUPINFO结构,其中包含了用于新进程创建的一些信息,如标准输入、标准输出和标准错误的处理方式、新进程的显示方式等等。
二、使用CreateProcessAsUser函数创建新的进程
使用CreateProcessAsUser函数创建新的进程,需要遵循以下步骤:
1. 获取用户令牌
使用LogonUser函数以用户名和密码的形式获取用户令牌。如果需要获取当前登录用户的令牌,则使用WTSQueryUserToken函数。获取到用户令牌后,需要调用DuplicateTokenEx函数创建一个可用于启动新进程的新令牌。
2. 填写启动信息
因为启动信息结构体占用的内存是不固定的,所以您需要通过初始化该结构体中的cb成员变量来指定所需要的内存大小,然后再将该结构体传递给CreateProcessAsUser函数。启动信息结构体中的其他成员变量可以设置为适当的值,比如hStdInput、hStdOutput和hStdError等。
3. 启动新进程
在填好了用户令牌和启动信息之后,您就可以调用CreateProcessAsUser函数来启动新进程了。这个函数将根据您提供的信息创建一个新的进程,并将其启动在指定的用户会话中以指定的用户身份运行。
三、启动新进程的示例代码
下面是一个使用CreateProcessAsUser函数来创建新进程的示例代码:
```
#define _WIN32_WINNT 0x0501
#include
int wmain(int argc, wchar_t** argv) {
HANDLE token;
PROCESS_INFORMATION pi;
STARTUPINFO si;
BOOL result;
wchar_t* command = L"C:\\Windows\\notepad.exe";
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
// 获取当前登录用户的令牌
WTSQueryUserToken(WTSGetActiveConsoleSessionId(), &token);
// 复制令牌以供新进程使用
DuplicateTokenEx(token, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &token);
// 启动新进程
result = CreateProcessAsUser(token, NULL, command, NULL, NULL, FALSE, CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, NULL, NULL, &si, &pi);
if (result) {
wprintf(L"Successfully launched %s\n", command);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else {
wprintf(L"Failed to launch %s, error %d\n", command, GetLastError());
}
CloseHandle(token);
return 0;
}
```
上面的代码首先使用WTSQueryUserToken函数获取当前登录用户的令牌,然后复制该令牌,并将其作为CreateProcessAsUser函数的第一个参数传入。接下来,代码将指定要启动的新进程的文件路径及其命令行参数,并将其作为CreateProcessAsUser函数的第三个参数传入。
四、CreateProcessAsUser函数的局限性
使用CreateProcessAsUser函数有一些局限性,这些局限性可能会影响到您的应用程序的性能和安全性。下面是一些需要注意的方面:
1. 只能在已登录的用户会话中启动新进程。
2. 不支持高CUI和无CUI模式。
3. 新进程所创建的窗口不能共享给其他会话的用户。
4. 仅限于在交互式会话中将进程启动为拥有特定用户安全标识符(SID)的用户。
5. 启动的新进程所继承的系统环境变量、用户环境变量等与当前进程的环境变量是不一样的。
6. 您需要拥有适当的权限才能获取用户令牌并使用CreateProcessAsUser函数创建新进程。
总结
通过使用CreateProcessAsUser函数可以很方便地启动一个新进程,而不会影响到当前用户的会话状态。如果您的应用程序需要在用户会话中启动一些线程或进程,或者需要在用户的用户账户下执行一些任务,那么这个Windows API就是您的理想之选。当然,在使用CreateProcessAsUser函数时需要注意其的局限性和要求的权限。