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

时间:2019-07-11 10:35:10

标签: c# winforms hook loadlibrary setwindowshookex

我正在开发一个可全局监听触摸事件的应用程序,并在该应用程序上设置了一个钩子来检索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 here上设置全局挂钩的信息。

  • 我还在应用程序窗口中调用了RegisterTouchWindow函数以启用接收触摸事件。

1 个答案:

答案 0 :(得分:0)

我将尝试尽可能详细地回答我的问题,以使其他初学者了解正在发生的事情。

首先,我遵循了如何从MSDN Hook Documentation创建钩子的指南,但是该示例显示了它在c ++上的用法。在使用SetWindowHookEx搜索了参考文献之后,我阅读了有关挂钩低级Windows挂钩的示例。这些挂钩(即WH_KEYBOARD_LLWH_MOUSE_LL)是最常见的教程,可以全局挂钩,而无需将其挂钩进程分离为dll。如果WH System Events的其余部分要全局挂接,则需要分开。文档中也对此进行了描述:

  

必须将全局挂钩过程放置在与安装挂钩过程的应用程序分开的DLL中。正在安装的应用程序必须具有DLL模块的句柄,然后才能安装挂钩过程。

背后的大概想法是,钩子函数被注入到所有正在运行的线程中。对于WH_KEYBOARD_LLWH_MOUSE_LL使用User32.dll作为其钩子库的情况,这很好。但是,如果像我一样将它用于其他系统事件,则该过程可能会使整个桌面崩溃,就像它发生的方式一样。

我的应用程序是用C#编码的,所以我必须用c ++创建一个dll,然后将其链接到我的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);
 }