CTRL_BREAK_EVENT到GUI应用程序将危及父进程



我创建了一个控制台应用程序,下面是代码。

这些代码将只是启动explorer.exe的子进程,然后向它发送一个CTRL_BREAK_EVENT,这是一个NO-OP,因为子explorer进程不是一个控制台应用程序。然后使用TerminateProcess来终止子进程,这也没有效果,但也可以。

问题是,在这些步骤之后,这个父进程的整个控制台事件系统被破坏了-我不能通过单击控制台窗口上的X或按CTRL-C来关闭这个控制台应用程序。


#include <Windows.h>
#include <iostream>
int main() {
const LPWSTR exe = const_cast<LPTSTR>(TEXT("C:\Windows\explorer.exe"));
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
CreateProcess(exe,
exe,
NULL,
NULL,
FALSE,
CREATE_NEW_PROCESS_GROUP,
NULL,
NULL,
&si,
&pi);
Sleep(1000);
GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pi.dwProcessId);
Sleep(1000);
TerminateProcess(pi.hProcess, 0);
Sleep(1000);
while (true) {
Sleep(1000);
std::cout << "Hello World!n";
}
}

我这样做是因为我正在制作一个应用程序托管平台,人们可以在私有云上上传和运行应用程序。我们不知道用户会上传什么样的ex。如果用户上传的控制台应用程序依赖于CTRL_BREAK_EVENT来实现安全退出,我们希望使其成为可能,因此我们首先尝试CTRL_BREAK_EVENT。如果程序在一段时间后没有及时关闭(例如GUI程序),我们将终止它,就像上面的代码所做的那样。如果我们在GUI应用程序上这样做,我们不希望它破坏整个控制台控制事件系统,因为我们依赖它来管理作为子进程运行的其他服务的生命周期。

顺便说一下,如果我们创建了带有创建标志&;detached_process &;的进程,即使EXE是一个控制台应用程序,控制台控制事件系统的破坏也会被破坏。

有办法解决这个问题吗?很多谢谢!

这是一个解决方案,以防止这个问题发生,我目前在我们的生产中使用,对于任何人谁是面临同样的问题。

  1. 使用QueryFullProcessImageName查找子进程的PE镜像文件路径
  2. 查找该PE映像的子系统。https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
  3. 如果子系统是GUI,不要使用GenerateConsoleCtrlEvent

如果您不熟悉PE格式,并且不想阅读文档,只需这样做:

  1. 读取PE文件的0x3c作为UINT16,以查找PE头的偏移量
  2. 读取UINT8PE_HEADER + 0x18 + 0x44,0x02表示GUI应用程序。

我不想把这个标记为答案,因为我希望有更优雅的方式。

最新更新