【发布时间】:2016-05-03 23:47:10
【问题描述】:
我们的 C++ 应用程序使用 CreateProcess 启动一个单独的 .exe(它可以启动自己的子进程),如下所示。
BOOL started = ::CreateProcess(NULL, // application
p, // parameters
NULL, // process security
NULL, // thread security
TRUE, // inherit handles flag
0, // flags
NULL, // inherit environment
dirLP, // inherit directory
&startup, // STARTUPINFO
&procinfo); // PROCESS_INFORMATIO
如果我们需要取消“作业”,我们使用 CreateToolhelp32Snapshot 遍历进程列表以查找我们启动的进程的任何子进程。
static BOOL TerminateProcessTree (HANDLE parentProcess,UINT exitCode)
{
BOOL result=TRUE;
HANDLE hProcessSnap = NULL;
PROCESSENTRY32 pe32 = {0};
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
return (FALSE);
pe32.dwSize = sizeof(PROCESSENTRY32);
// Walk the snapshot of the processes
DWORD parentID=GetProcessId(parentProcess);
if(parentID==0){
PrintLastError("GetProcessId");
return FALSE;
}
if (Process32First(hProcessSnap, &pe32)) {
do{
if(pe32.th32ParentProcessID==parentID){
HANDLE hProcess = OpenProcess (PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
if(hProcess!=NULL){
BOOL terminateChildren=TerminateProcessTree(hProcess,exitCode);
BOOL terminatedChild = TerminateProcess(hProcess, exitCode);
if (!terminatedChild){
PrintLastError("TerminateProcess");
}
CloseHandle(hProcess);
if(!terminatedChild || !terminateChildren){
result=FALSE;
break;
}
} else{
PrintLastError("OpenProcess");
}
}
}while (Process32Next(hProcessSnap, &pe32));
}
CloseHandle (hProcessSnap);
DWORD checkCode=0;
BOOL terminated;
if(GetExitCodeProcess(parentProcess,&checkCode) && checkCode==STILL_ACTIVE){
terminated=TerminateProcess(parentProcess,exitCode);
if (!terminated){
PrintLastError("TerminateProcess");
result= FALSE;
}
}
return result;
}
如前所述,这在 Windows 7 上运行良好。Windows 10 在第一次调用“TerminateProcess”时出现“拒绝访问”失败。显然,Windows 安全模型在进程方面发生了一些变化。
【问题讨论】:
-
您是否验证
OpenProcess成功,提供有效句柄? -
这似乎是一种非常复杂的方式来终止您创建的进程。为什么不直接使用
PROCESS_INFORMATION结构中返回的进程句柄CreateProcess? -
@MrEricSir 他说 CrateProcess 是由终止进程的子进程调用的。
-
要详细说明 Alf 的评论,请查看 MSDN 上的Job Objects:“进程与作业关联后,默认情况下,它使用 CreateProcess 创建的任何子进程也与作业相关联." 所以你可以使用
CreateJobObject()和AssignProcessToJobObject()将初始进程与作业相关联,然后让它创建它想要的任何子进程,然后你可以使用TerminateJobObject()终止当前关联的所有进程工作。 -
显然我不是 100% 清楚我的问题。我正在创建一个“可能”也启动一些(子)进程的进程。我掌握了“顶级”流程。稍后,只有顶级进程的句柄,我需要杀死“进程树”。这可以通过枚举进程并定位该树的成员并调用 TerminateProcess 来完成。这在 W7 上运行良好。在 W10 上,TerminateProcess 失败并显示“拒绝访问”。我意识到一个解决方案是采用“作业对象”,但我试图了解 Windows 10 安全模型的哪些部分发生了变化