如何添加系统"窗钩"这样创建的窗口被通知/启动? [英] How to add a system "windows hook" so as to be notified of windows being created/activated?

查看:219
本文介绍了如何添加系统"窗钩"这样创建的窗口被通知/启动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试了一堆东西,但我不能让它际我的任务栏被核爆和我的桌面UI等超自然效果持续工作。



使用尝试开放式图书馆 http://mwinapi.sourceforge.net/ 第一。虽然它很好地担任了OO层枚举窗口和东西。它不能做正确的钩子



下一站是的迪诺E.对windows钩子后在.NET Framework 。最后我写我自己的类型,因为我是理解的文字,并试图得到这个工作。



我的目的是使这个程序运行,有它能够记录所有创建的窗口正在运行时。号召所有的眼球...



更新:剪断,因为显然你的无法使用.NET编写全球windows钩子/托管代码(除了一些低级别鼠标或键盘钩子)



所以我切换到C ++。还是所有WinAPI的调用返回的句柄有效,但我没有看到被称为我的过滤功能 - 似乎没有被收到任何通知。仍然无法正常工作......有人能找出错误。

 无效CWinHookFacade ::钩()
{
HMODULE hCurrentDll =调用LoadLibrary(_T([路径到我的钩子DLL]));
m_HookHandle =调用SetWindowsHookEx(WH_CBT,
FilterFunctionForHook,
hCurrentDll,
0);
如果(m_HookHandle == NULL)
{
抛出新的std ::异常(无法勾);
}

}
无效CWinHookFacade ::脱开()
{
如果(!UnhookWindowsHookEx(m_HookHandle))
{
抛出新的std ::例外(脱开失败!);
}
m_HookHandle = NULL;
}

LRESULT CWinHookFacade :: FilterFunctionForHook(INT代码,WPARAM wParam参数,LPARAM lParam的)
{
如果(代码> = 0)
{
开关(代码)
{
情况下HCBT_CREATEWND:
wprintf(_T(创建的窗口));
中断;
情况下HCBT_ACTIVATE:
wprintf(_T(弹出窗口));
中断;
情况下HCBT_DESTROYWND:
wprintf(_T(毁灭之窗));
中断;
}
}

返回CallNextHookEx方法(m_HookHandle,代码的wParam,lParam的);
}



客户端EXE调用Hook_DLL这样

  INT _tmain(INT ARGC,_TCHAR *的argv [])
{
CWinHookFacade ::胡克();
的getchar();
CWinHookFacade ::脱开();
}


解决方案

我想问题,你'再有是因为你想实现在C#中的钩子函数。基于 pinvoke.net的文档和SetWindowsHookEx(),它说,你不能做到这一点 - 钩子过程必须是在非托管的DLL。否则,这将你的DLL加载到与消息循环,这将反过来导致加载CLR和在每一个过程开始的所有运行的进程。这不仅需要很长的时间,但注射到CLR的所有进程可能不是最好的主意。此外,会发生什么,如果一个进程已经有一个正在运行的CLR是从你的DLL是建立针对不同?



最好的办法是这段代码移到非托管C ++ DLL,并使用某种形式的进程间通信的发送你的钩子程序返回到您的应用程序截获的数据。



更新



首先(这大概是不会导致您的问题),你为什么叫调用LoadLibrary()来获得 HINSTANCE 您的DLL的?它可能会更好调用的GetModuleHandle()由于您的DLL已经加载



至于为什么你的钩子程序不会被调用 - 你怎么样验证了这一点?既然你是挂钩的所有GUI线程系统,这意味着你的DLL需要被加载到所有的GUI程序。这可能是因为你不会看到调用的结果 wprintf(),因为其他进程不具有一个控制台窗口到显示输出。



要验证您的DLL装入正确,使用的程序,列出了一个过程(我喜欢的 Process Explorer的)。您可以使用查找|查找处理或DLL菜单项来搜索您的DLL的名字 - 它应与一个消息循环的所有进程显示



一旦你验证了你的DLL是装,看你的钩子叫您可以将调试器附加到另一个进程(如记事本),然后在你的钩子函数设置断点。当消息被发送到CBT钩子应熄灭。如果你不想使用调试器,那么你可以切换到 wprintf调用()来的的OutputDebugString()并运行像的 DebugView中以监测结果。



最后,因为你的钩子函数被调用另一个进程的背景下,您的 m_HookHandle 变量将是无效的存在。你应该将其存放在共享数据段让您的DLL的加载的所有实例将具有相同值。


Tried a bunch of things but I can't get it to work consistently amid my taskbar being nuked and other supernatural effects on my desktop UI.

Tried using a open-library http://mwinapi.sourceforge.net/ first. Although it worked nicely as an OO layer for enumerating windows and stuff. It couldn't do hooks properly

Next stop was Dino E.'s post on Windows Hooks in the .Net framework. I ended up writing my own type as I was understanding the text and trying to get this to work.

My intention is to have this app running and have it be able to log all created windows while it is running. Calling all eyeballs...

Update: Snipped since apparently you can't write global windows hooks in .Net / managed code (except some low level mouse or keyboard hooks)

So I switched to C++. Still all WinAPI calls return valid handles but I don't see my filter function being called - don't seem to be receiving any notifications. Still doesn't work... Can someone spot the mistake.

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);
}

Client exe calls the Hook_DLL like this

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

解决方案

I think the problems you're having are because you're trying to implement a hook function in C#. Based on pinvoke.net's documentation on SetWindowsHookEx(), it says that you can't do this - the hook procedure must be in an unmanaged DLL. Otherwise, this would load your DLL into all running processes with a message loop, which would in turn cause the CLR to be loaded and started in each process. Not only would this take a long time, but injecting the CLR into all processes probably isn't the best idea. Plus, what happens if a process already has a running CLR that is a different from from what your DLL was built against?

The best approach would be to move this code to an unmanaged C++ DLL, and use some sort of interprocess communication to send the data intercepted by your hook procedure back to your application.

Update

First (and this is probably not causing your issue), why are you calling LoadLibrary() to get the HINSTANCE of your DLL? It would probably be better to call GetModuleHandle() since your DLL is already loaded.

As for why your hook procedure is never called - how have you verified this? Since you are hooking all GUI threads in the system, this means that your DLL needs to be loaded into all GUI processes. It's likely that you won't see the results of calling wprintf() because the other processes don't have a console window up to show the output.

To verify that your DLL is loaded properly, use a program that lists the DLLs loaded by a process (I like Process Explorer). You can use the Find | Find Handle or DLL menu item to search for the name of your DLL - it should show up in all processes with a message loop.

Once you have verified that your DLL is loaded, to see if your hook is called you can attach a debugger to another process (such as Notepad), and then set a breakpoint in your hook function. That should go off whenever a message is sent to the CBT hook. If you don't want to use a debugger, then you can change the calls to wprintf() to OutputDebugString() and run a utility like DebugView to monitor the results.

Finally, since your hook function is called in the context of another process, your m_HookHandle variable will not be valid there. You should store it in a shared data segment so that all loaded instances of your DLL will have the same value.

这篇关于如何添加系统"窗钩"这样创建的窗口被通知/启动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆