我有一个 Win32 C++ 应用程序。我正在尝试使用
CreateProcess
启动一个或多个子进程。我希望当父母关闭时,孩子也关闭。
我通过创建工作并启用
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
实现了这一目标:
HANDLE hJob = CreateJobObject(NULL, NULL);
JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo;
ZeroMemory(&extendedInfo, sizeof(extendedInfo));
extendedInfo.BasicLimitInformation.LimitFlags =
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
SetInformationJobObject(
hJob, JOBOBJECTINFOCLASS::JobObjectExtendedLimitInformation,
&extendedInfo, sizeof(extendedInfo));
然后将当前(父)和创建(子)进程添加到此作业中:
// assign parent to job
AssignProcessToJobObject(hJob, GetCurrentProcess());
// launch child with no inherited handles
PROCESS_INFORMATION procInfo;
ZeroMemory(&procInfo, sizeof(procInfo));
STARTUPINFOA startInfo;
ZeroMemory(&startInfo, sizeof(startInfo));
startInfo.cb = sizeof(startInfo);
startInfo.dwFlags |= STARTF_USESTDHANDLES;
bool success = CreateProcessA(NULL,
"test.exe", // command line
NULL, // process security attributes
NULL, // primary thread security attributes
FALSE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&startInfo, // STARTUPINFO pointer
&procInfo); // receives PROCESS_INFORMATION
// assign child to job
AssignProcessToJobObject(hJob, procInfo.hProcess);
这可行,但父应用程序和子应用程序(
main.exe
和test.exe
)在任务管理器中显示为两个不相关的进程:
(即使关闭 main.exe 也会关闭 test.exe)。
我的做法与 Microsoft Teams 或 Chrome 等有嵌套流程的产品有何不同?
任务管理器到底在做什么没有记录。
在 Windows 8 中,它不会对子进程进行分组,它仅根据具有窗口的进程或“特殊”进行组织。
任务管理器如何将进程分类为应用程序、后台进程或Windows进程?:
这些是任务管理器简单编造的术语。系统本身并不真正关心它们是什么类型的进程。
如果进程有可见窗口,则任务管理器将其称为“应用程序”。
如果进程被标记为关键,则任务管理器将其称为“Windows 进程”。
否则,任务管理器将其称为“后台进程”。
(我不相信这是 100% 准确的,它清楚地了解服务,我怀疑它可能会硬编码一些名称)
在 Windows 10 中,它更努力地将事物组合在一起,但我并不完全知道它在做什么。
通常(但并非总是)能够将 conhost.exe 子进程绑定到其父控制台应用程序。
记事本和画图的新奇特商店/打包版本将所有进程都放在一个组中。 Notepad2 不会发生同样的情况,即使它设置了应用程序模型 ID。它也不适用于写字板(即使一个是另一个的子代)。我还尝试在一个小测试应用程序中设置 AMUI,但进程范围的 AMUI 和每 HWND AMUI 似乎都不会触发分组。
作业对象似乎未启用分组。
根据您的版本,Edge 可能会使用特殊的 API 告诉任务管理器其进程。
总之,我不知道它到底在寻找什么,但打包应用程序和应用程序容器似乎经常触发它。
要使其在任务管理器中作为子进程可见,您必须在启动进程之前将 StartInfo 属性中的 CreateNoWindow 属性设置为 false,并将 UseShellExecute 属性设置为 false。
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
这告诉进程为子进程创建一个新窗口,并使用命令行来启动进程,而不是使用 shell 来启动进程。 现在,这将在任务管理器中创建子进程作为新的可见进程,并将显示在主进程的树下。
最后找到解决办法了吗?