首先来看一下CreatProcess函数的原型:
BOOL CreateProcess( LPCWSTR lpApplicationName, //指定可执行文件的文件名
LPCWSTR lpCommandLine, //指定可执行文件的运行参数
LPSECURITY_ATTRIBUTES lpProcessAttributes, //进程安全属性
LPSECURITY_ATTRIBUTES lpThreadAttributes, //线程安全属性
BOOL bInheritHandles, //指定当前进程中的可继承句柄是否可以被新的进程继承
DWORD dwCreationFlags,//指定新进程的优先级和其他创建标志
LPVOID lpEnvironment, //指定新进程的环境变量
LPWSTR lpCurrentDirectory, //指定新进程使用的当前目录
LPSTARTUPINFO lpStartupInfo, //指定新进程使用的启动信息
LPPROCESS_INFORMATION lpProcessInformation//返回新的进程和线程的相关信息
);
其中在创建可继承的子进程这个过程中,第五个参数要设置为TURE,但是事实上还有一个信息容易被漏掉造成继承失败,
那就是第3个参数,关于线程安全的,先看一下SECURITY_ATTRIBUTES这个结构体的信息:
typedef struct _SECURITY_ATTRIBUTES { DWORD nLength; LPVOID lpSecurityDescriptor; BOOL bInheritHandle; } SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES;
该结构体的第三个参数指定了进程是否能被继承,所以我们要创建一个可继承的进程,除了设置CreatProcess第五个参数以外,还需要设置这个结构体。
下面这个例子是打开一个计算器,再打开一个程序,在程序中将前面打开的计算器关闭:
//创建计算器进程 SECURITY_ATTRIBUTES sa = {0}; sa.nLength = sizeof(sa); sa.bInheritHandle = TRUE; //此句柄可以继承 STARTUPINFO si = {0}; si.cb = sizeof(si); PROCESS_INFORMATION pi = {0}; if (!CreateProcess("calc.exe", // NULL, &sa, //创建的计算器进程可以被继承 NULL, TRUE, CREATE_FORCEDOS, NULL, NULL, &si, &pi)) { AfxMessageBox("创建进程失败"); } //将计算机进程做参数传给子进程 CString str; str.Format("CloseCalc.exe %08x", pi.hProcess); //打开一个关闭计算器的程序 STARTUPINFO si2 = {0}; si2.cb = sizeof(si2); PROCESS_INFORMATION pi2 = {0}; if (!CreateProcess(NULL, (LPSTR)(LPCSTR)str, NULL, NULL, TRUE, CREATE_FORCEDOS, NULL, NULL, &si2, &pi2)) { AfxMessageBox("创建进程失败"); }
关闭计算器的程序如下:
int main(int argc, char* argv[]) { HANDLE hProcess = (HANDLE)strtoul(argv[1], NULL, 16); TerminateProcess(hProcess, 0); CloseHandle(hProcess); return 0; }