explorer.exe 在通过 WH_GETMESSAGE 启用全局触摸挂钩时崩溃

explorer.exe crashes when global touch hook via WH_GETMESSAGE is enabled

我正在开发一个在全球范围内监听触摸事件的应用程序,我已经为它设置了一个钩子来检索 WM_TOUCH 消息。此消息将从 WH_GETMESSAGE 挂钩中检索。

问题是每次我 运行 应用程序 explorer.exe 都会崩溃,需要很长时间才能再次打开。有没有懂这个问题的人?我以前用 WH_KEYBOARD_LL 做过这个,但它没有做同样的事情。

这个,那个,我仍然没有得到任何全局触摸事件。

我的钩子设置如下:

public void hook() {
            IntPtr hInstance = LoadLibrary("User32");
            hhook = SetWindowsHookEx(WH_GETMESSAGE, hookProc, hInstance, 0); // set Thread ID to 0 to listen to all threads within the same desktop
}

我会尽可能详细地回答我的问题,以便其他初学者了解发生了什么。

首先,我遵循了有关如何从 MSDN Hook Documentation 创建挂钩的指南,但该示例显示了它在 C++ 上的用法。在搜索了使用 SetWindowHookEx 的参考资料后,我阅读了关于处理低级别 windows 挂钩的示例。这些钩子,即 WH_KEYBOARD_LLWH_MOUSE_LL,是最常见的教程,可以全局挂钩,无需将它们的 Hook Process 分离到一个 dll 中。 WH System Events 的其余部分如果要全局挂钩则需要分离。文档中也对此进行了描述:

You must place a global hook procedure in a DLL separate from the application installing the hook procedure. The installing application must have the handle to the DLL module before it can install the hook procedure.

背后的粗略想法是将钩子函数注入所有 运行 线程。对于使用 User32.dll 作为其钩子库的 WH_KEYBOARD_LLWH_MOUSE_LL 的情况,这很好。但是如果你像我一样将它用于其他系统事件,这个过程可能会像我的那样使你的整个桌面崩溃。

我的应用程序是用 C# 编写的,所以我必须用 C++ 创建一个 dll,然后 link 它到我的 C# 应用程序。另外,阅读 pInvokes 以能够使用 LoadLibraryGetProcAddress

您可以从 Visual Studio 本身创建 dll 个文件。您只需修改 dllmain.cpp 文件。我玩弄了这个 example

中的 WH_GETMESSAGE

在我的 C# 应用程序中,我所要做的就是像这样调用 SetHook 函数:

IntPtr hInstance = IntPtr.Zero;
IntPtr hProc = IntPtr.Zero;

private delegate void HookSetting();

public void SetHook()
{
        hInstance = LoadLibrary("Dll1");

        if (IntPtr.Zero == hInstance)
        {
            //do a null check
        }
        hProc = GetProcAddress(hInstance, "_SetHook@0"); // SetHook is in its "mangled" form right here
        if(IntPtr.Zero == hProc)
        {
            //do a null check
        }

        //Ways of starting the Hook:
        // OPTION 1: calling the SetHook function of the DLL within the C# app.
        //HookSetting hookset = (HookSetting)Marshal.GetDelegateForFunctionPointer(hProc, typeof(HookSetting));
        //hookset();

        // OPTION 2: Instead of using the SetHook function, call the SetwindowsHookEx directly 
        hhook = SetWindowsHookEx(WH_GETMESSAGE, hProc, hInstance, 0);
 }