gpt4 book ai didi

c# - 如何添加系统 "windows hook"以便在创建/激活窗口时收到通知?

转载 作者:太空狗 更新时间:2023-10-29 22:56:19 25 4
gpt4 key购买 nike

尝试了很多东西,但在我的任务栏被破坏和我的桌面 UI 上出现其他超自然效果的情况下,我无法让它始终如一地工作。

尝试使用开放式库 http://mwinapi.sourceforge.net/第一的。尽管它作为 OO 层可以很好地用于枚举窗口和其他东西。它不能正确地做钩子(Hook)

下一站是 Dino E.'s post on Windows Hooks in the .Net framework .当我理解文本并试图让它发挥作用时,我最终编写了自己的类型。

我的意图是让这个应用程序运行并让它能够在运行时记录所有创建的窗口。吸引所有眼球...

更新:因为显然是你can't write global windows hooks in .Net而被剪掉了/托管代码(一些低级鼠标或键盘钩子(Hook)除外)

所以我转向了 C++。所有 WinAPI 调用仍然返回有效句柄,但我没有看到我的过滤器函数被调用 - 似乎没有收到任何通知。仍然不起作用...有人可以发现错误吗。

void CWinHookFacade::Hook()
{
HMODULE hCurrentDll = LoadLibrary(_T("[Path to my hook dll]"));
m_HookHandle = SetWindowsHookEx(WH_CBT,
FilterFunctionForHook,
hCurrentDll,
0);
if (m_HookHandle == NULL)
{
throw new std::exception("Unable to hook");
}

}
void CWinHookFacade::Unhook()
{
if (!UnhookWindowsHookEx(m_HookHandle))
{
throw new std::exception("Unhook failed!");
}
m_HookHandle = NULL;
}

LRESULT CWinHookFacade::FilterFunctionForHook(int code, WPARAM wParam, LPARAM lParam)
{
if (code >= 0)
{
switch(code)
{
case HCBT_CREATEWND:
wprintf(_T("Created Window"));
break;
case HCBT_ACTIVATE:
wprintf(_T("Activated Window"));
break;
case HCBT_DESTROYWND:
wprintf(_T("Destroy Window"));
break;
}
}

return CallNextHookEx(m_HookHandle, code, wParam, lParam);
}

客户端exe这样调用Hook_DLL

int _tmain(int argc, _TCHAR* argv[])
{
CWinHookFacade::Hook();
getchar();
CWinHookFacade::Unhook();
}

最佳答案

我认为您遇到的问题是因为您试图在 C# 中实现 Hook 函数。基于pinvoke.net's documentationSetWindowsHookEx() 上,它表示您不能这样做 - Hook 过程必须在非托管 DLL 中。否则,这会使用消息循环将您的 DLL 加载到所有正在运行的进程中,这又会导致在每个进程中加载​​和启动 CLR。这不仅会花费很长时间,而且将 CLR 注入(inject)所有进程可能也不是最好的主意。另外,如果一个进程已经有一个正在运行的 CLR 与您的 DLL 的构建对象不同,会发生什么情况?

最好的方法是将此代码移动到非托管 C++ DLL,并使用某种进程间通信将钩子(Hook)过程截获的数据发送回您的应用程序。

更新

首先(这可能不会导致您的问题),您为什么要调用 LoadLibrary() 来获取 DLL 的 HINSTANCE?最好调用 GetModuleHandle()因为您的 DLL 已经加载。

至于为什么你的 Hook 程序从未被调用——你是如何验证的?由于您正在 Hook 系统中的所有 GUI 线程,这意味着您的 DLL 需要加载到所有 GUI 进程中。您可能看不到调用 wprintf() 的结果,因为其他进程没有显示输出的控制台窗口。

要验证您的 DLL 是否已正确加载,请使用列出进程加载的 DLL 的程序(我喜欢 Process Explorer)。您可以使用查找 |查找句柄或 DLL 菜单项以搜索您的 DLL 的名称 - 它应该显示在所有带有消息循环的进程中。

一旦您验证了您的 DLL 已加载,要查看您的 Hook 是否被调用,您可以将调试器附加到另一个进程(例如记事本),然后在您的 Hook 函数中设置一个断点。每当将消息发送到 CBT Hook 时,它就会关闭。如果您不想使用调试器,则可以将对 wprintf() 的调用更改为 OutputDebugString()并运行类似 DebugView 的实用程序监测结果。

最后,由于您的 Hook 函数是在另一个进程的上下文中调用的,因此您的 m_HookHandle 变量在那里无效。您应该将其存储在 shared data segment 中这样您的 DLL 的所有加载实例都将具有相同的值。

关于c# - 如何添加系统 "windows hook"以便在创建/激活窗口时收到通知?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/964564/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com