SetWinEventHook与CreateProcess,C ++

时间:2013-12-22 17:31:48

标签: c++ createprocess

我正在用CreateProcess打开一个窗口,我在理解SetWinEventHook方面遇到了很多麻烦。

在调用函数中,我有:

HWINEVENTHOOK hook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, NULL, WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT );

BOOL result = CreateProcess(0, arguments,
                    NULL, NULL, FALSE, 0, NULL,
                    NULL, &StartupInfo, &ProcessInfo)

if (hook) {
    UnhookWinEvent(hook);
}

创建进程顺利进行,但未调用链接到SetWinEventHook的WinEventProc函数。为了让WinEventProc被调用,我尝试过这样的事情:

MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0);

在createProcess调用之后,但我不知道如何结束while循环,所以它会持续进行。

我已经做了很多阅读,但我不明白如何使用SetWinEventHook来捕获由CreateProcess启动的进程。任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:4)

您可能需要完整且有效的事件循环 - 尝试:

MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
  TranslateMessage(&msg);
  DispatchMessage(&msg);
}

如果您的应用程序不是GUI应用程序 - 或者更具体地说,如果您不需要事件循环而不是钩子 - 您可以添加另一个线程并使用上面的事件循环(以及所有挂钩和取消挂钩)我想),或者将PeekMessageGetMessage结合使用来创建非阻塞事件循环并定期调用它。

其次,在调用CreateProcess后,您不应该直接删除挂钩。通常在程序完全加载和初始化之后创建窗口,并且此过程可能需要一段时间。 CreateProcess异步工作,这意味着它不会在退出之前等待所有这一切。

第三,为了能够接收任何类型的挂钩消息,您的消息循环需要在SetWinEventHookUnhookWinEvent之间执行 - 在任何其他情况下,您将无法获得任何内容。

最后,为了避免来自其他进程的消息传递给您的进程,您应该使用CREATE_SUSPENDED标志启动应用程序,使用适当的进程ID启动挂钩,然后使用{{1}继续执行进程主要线程句柄从ResumeThread获得。

总的来说,它应该看起来像:

CreateProcess

如果您的应用程序不是事件驱动的 - 只是常规顺序应用程序,那么您应该定期调用上面的事件循环,直到您的BOOL result = CreateProcess(0, arguments, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &StartupInfo, &ProcessInfo); HWINEVENTHOOK hook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, NULL, WinEventProc, ProcessInfo.dwProcessId, 0, WINEVENT_OUTOFCONTEXT ); ResumeThread(ProcessInfo.hThread); // If you don't have an event loop function in your application already, then you could insert a temporary one here. MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } 执行 - 您可能应该添加一些安全保护变量以查看它是否已经执行。另一个好主意可能是包括一些超时(2-3分钟?),以防没有发布任何事件(应用程序崩溃,app由于某种原因没有创建任何对象)。为简单起见,我也跳过了任何错误检查。

你的钩子程序应该做那样的事情:

WinEventProc

修改

至于跳过消息循环 - 是的,这就是这个消息循环应该做的事情。

哪个消息循环最适合你取决于你的程序构造 - 如果你已经运行了一个偶数循环(像Qt这样的GUI框架,MFC ......通常已经为你实现了),那么你不需要无论如何添加任何。如果您希望您的应用程序等到WinEvent交付,那么您应该执行类似的操作:

void CALLBACK WinEventProc(
    HWINEVENTHOOK hWinEventHook,
    DWORD event,
    HWND hwnd,
    LONG idObject,
    LONG idChild,
    DWORD dwEventThread,
    DWORD dwmsEventTime)
{
    // This will handle the re-entrance problem nicely.
    UnhookWinEvent(hWinEventHook);

    // Do wathever you need to do with a window here.
    [...]

}

挂钩功能应该:

//Global variable for stop-condition:
bool docontinue = false;

void CALLBACK WinEventProc(
    HWINEVENTHOOK hWinEventHook,
    DWORD event,
    HWND hwnd,
    LONG idObject,
    LONG idChild,
    DWORD dwEventThread,
    DWORD dwmsEventTime)
{
    // This will handle the re-entrance problem nicely.
    UnhookWinEvent(hWinEventHook);

    // Do wathever you need to do with a window here.
    [...]
    docontinue = false;
}

这是最天真的方法,它有几个缺点,但如果你只需要做一个简单的操作,那么它可能就足够了。