CreateProcess
创建一个新进程及主线程。新进程在调用进程的安全上下文中运行;
函数声明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| WINBASEAPI BOOL WINAPI CreateProcessA( _In_opt_ LPCSTR lpApplicationName, _Inout_opt_ LPSTR lpCommandLine, _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _In_ BOOL bInheritHandles, _In_ DWORD dwCreationFlags, _In_opt_ LPVOID lpEnvironment, _In_opt_ LPCSTR lpCurrentDirectory, _In_ LPSTARTUPINFOA lpStartupInfo, _Out_ LPPROCESS_INFORMATION lpProcessInformation );
WINBASEAPI BOOL WINAPI CreateProcessW( _In_opt_ LPCWSTR lpApplicationName, _Inout_opt_ LPWSTR lpCommandLine, _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _In_ BOOL bInheritHandles, _In_ DWORD dwCreationFlags, _In_opt_ LPVOID lpEnvironment, _In_opt_ LPCWSTR lpCurrentDirectory, _In_ LPSTARTUPINFOW lpStartupInfo, _Out_ LPPROCESS_INFORMATION lpProcessInformation );
#ifdef UNICODE #define CreateProcess CreateProcessW #else #define CreateProcess CreateProcessA #endif
|
参数
lpApplicationName
要执行的模块的名称。lpApplicationName
参数可以是NULL
, 要运行批处理文件, 必须启动命令解释程序, 并将lpApplicationName
设置成cmd.exe
;
lpCommandLine
要执行的命令行。lpCommandLine
的参数可以是NULL
, 在这种情况下, 该函数使用由lpApplicationName
指向的字符串作为命令行。如果lpApplicationName
和lpCommandLine
都不为NULL
, 则由lpApplicationName
指向的以空字符串结尾的字符串会指定要执行的模块, 并且由lpCommandLine
指向的以空字符串结尾的字符串会指定命令行;
lpProcessAttributes
指向SECURITY_ATTRIBUTES
结构的指针, 用于确定是否可以由子进程继承返回新进程对象的句柄。如果lpProcessAttributes
为NULL
, 则不能继承句柄;
lpThreadAttributes
指向SECURITY_ATTRIBUTES
结构的指针, 用于确定是否可以由子进程继承返回的新线程对象的句柄。如果lpThreadAttributes
为NULL
, 则不能继承句柄;
bInheritHandles
如果此参数为TRUE
, 则调用进程中的每个可继承句柄都将由新进程来继承。如果该参数为FALSE
, 则不会继承句柄;
dwCreationFlags
控制优先级和创建进程的标志。例如, CREATE_NEW_CONSOLE
表示新进程将使用一个新控制台, 而不是继承父进程的控制台。CREATE_SUSPENDED
表示新进程的主线程会以暂停的状态来创建, 直到调用ResumeThread
函数时才运行;
lpEnvironment
指向新进程的环境块的指针。如果此参数为NULL
, 则新进程将使用调用进程的环境;
lpCurrentDirectory
指向进程当前目录的完整路径。该字符串还可以指定UNC
路径, 如果此参数为NULL
, 则新进程将具有与调用进程相同的当前驱动器和目录;
lpStartupInfo
指向STARTUPINFO
或STARTUPINFOEX
结构的指针。STARTUPINFO
或STARTUPINFOEX
中的句柄在不需要时必须由CloseHandle
关闭;
指向PROCESS_INFOMATION
结构的指针。用于接收有关新进程的标识信息。PROCESS_INFOMATION
中的句柄必须在不需要时由CloseHandle
关闭;
返回值
如果函数成功, 则返回值非零;
如果函数失败, 则返回值为零;
代码示例
1 2 3 4 5 6 7 8 9 10 11 12
| STARTUPINFO si = { 0 }; PROCESS_INFOMATION pi = { 0 }; si.cb = sizeof(STARTUPINFO); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = uiCmdShow; BOOL bRet = CreateProcess(NULL, "cmd.exe", NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); if (bRet == FALSE) { CloseHandle(pi.hThread); CloseHanle(pi.hProcess); return; }
|
使用事项-1
CreateProcess
着重注意5个参数: 执行模块名称的参数lpApplicationName
、执行命令行的参数lpCommandLine
、控制进程优先级和创建进程标志的参数dwCreationFlags
、指向STARTUPINFO
信息结构的参数lpStartupInfo
、以及指向PROCESS_INFOMATION
信息结构的参数lpProcessInformation
;
使用事项-2
CreateProcess
函数在指定窗口显示方式时, 需要在STARTUPINFO
结构体中将启用标志设置成STARTF_USESHOWWINDOW
, 表示wShowWindow
成员显示方式有效。然后将wShowWindow
设置为SW_HIDE
隐藏窗口, 创建方式为CREATE_NEW_CONSOLE
创建一个新控制台;
创建进程时共享句柄表
在创建进程中创建一个进程(比如WeChat进程), 并设定该子进程的进程内核句柄与主线程内核句柄为可继承;
在A进程中再创建一个进程B, 在进程B中对WeChat进程控制;
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
#include <iostream> #include <windows.h>
int main() { WCHAR wcBuffer[256]{}; WCHAR wcHandle[10]{};
SECURITY_ATTRIBUTES sa_p{}; sa_p.nLength = sizeof(SECURITY_ATTRIBUTES); sa_p.lpSecurityDescriptor = NULL; sa_p.bInheritHandle = TRUE;
SECURITY_ATTRIBUTES sa_t{}; sa_t.nLength = sizeof(SECURITY_ATTRIBUTES); sa_t.lpSecurityDescriptor = NULL; sa_t.bInheritHandle = TRUE;
STARTUPINFO si = { sizeof(STARTUPINFO) }; PROCESS_INFORMATION pi{};
const char* szCmdLine = "D:\\Tencent\\WeChat\\WeChat.exe"; WCHAR wcCmdLine[256]{}; wsprintf(wcCmdLine, L"%S", szCmdLine); if (FALSE == CreateProcess(NULL, wcCmdLine, &sa_p, &sa_t, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) { printf("WeChat CreateProcess Failed\n"); return 0; }
wsprintf(wcHandle, L"%x %x", pi.hProcess, pi.hThread); wsprintf(wcBuffer, L"D:\\Visual Studio Projects\\DiShui Projects\\05_20_Test_Demo\\ConsoleApplication1\\x64\\Debug\\ConsoleApplication2.exe %s", wcHandle);
STARTUPINFO si_B = { sizeof(STARTUPINFO) }; PROCESS_INFORMATION pi_B{};
if (FALSE == CreateProcess(NULL, wcBuffer, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si_B, &pi_B)) { printf("CreateProcess Failed\n"); return 0; } return 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
#include <iostream> #include <windows.h>
int main(int argc, char* argv[]) { DWORD dwProcessHandle = -1; DWORD dwThreadHandle = 0; WCHAR wcBuffer[256]{};
printf("%s %s\n", argv[1], argv[2]); MultiByteToWideChar(CP_ACP, 0, argv[1], -1, wcBuffer, sizeof(wcBuffer) / sizeof(WCHAR)); swscanf(wcBuffer, L"%x", &dwProcessHandle); printf("%x\n", dwProcessHandle); memset(wcBuffer, 0, 256); MultiByteToWideChar(CP_ACP, 0, argv[2], -1, wcBuffer, sizeof(wcBuffer) / sizeof(WCHAR)); swscanf(wcBuffer, L"%x", &dwThreadHandle); printf("%x\n", dwThreadHandle);
printf("获取父进程句柄、主线程句柄\n"); Sleep(5000); printf("挂起主线程\n"); SuspendThread((HANDLE)dwThreadHandle);
Sleep(5000);
printf("恢复主线程\n"); ResumeThread((HANDLE)dwThreadHandle);
Sleep(5000);
TerminateProcess((HANDLE)dwProcessHandle, 1); WaitForSingleObject((HANDLE)dwProcessHandle, INFINITE); printf("ID进程已经关闭\n");
system("pause"); }
|