1

主观的...哈哈

好的,所以我一直在 internetz 上寻找一个合理的解决方案来捕获多个击键,并且遇到了一些使用相同东西(键盘挂钩)的解决方案。一种解决方案使用本机调用按名称获取进程的 IntPtr,另一种使用 LoadLibrary("User32.dll")

所以我想我会“聪明”并做到了(成功)

IntPtr hInstance = Process.GetCurrentProcess().MainModule.BaseAddress;
callbackDelegate = new HOOKPROC(HookCallback);
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, callbackDelegate, hInstance, 0);

与使用此相反

IntPtr hInstance = LoadLibrary("User32.dll");
callbackDelegate = new HOOKPROC(HookCallback);
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, callbackDelegate, hInstance, 0);

一个比另一个更安全吗?我是否犯了一个没有显示其头部的致命错误?

4

2 回答 2

3

SetWindowsHookEx() 需要一个有效的模块句柄。它使用它来确定需要将哪些 DLL 注入其他进程才能使钩子工作。

但这只是全局挂钩的要求。两个低级挂钩(WH_MOUSE_LL 和 WM_KEYBOARD_LL)是特殊的,它们不需要 DLL 注入。Windows 仅在您自己的进程中调用挂钩回调。唯一的要求是您的线程泵送一个消息循环,以便 Windows 可以进行回调。Application.Run() 是必需的。

另外,您可以使低级挂钩在 C# 中工作的原因是,全局挂钩使用的 DLL 不能用托管语言编写,因为注入的进程不会加载 CLR。

怪癖是 SetWindowsHookEx() 检查您是否传递了有效的模块句柄,但实际上并没有将它用于低级挂钩。因此,您传递的任何有效句柄都可以使用。顺便说一句,这个怪癖在 Windows 7 SP1 中得到了修复,它不再执行该检查。

于 2013-01-10T15:12:54.377 回答
0

编辑:我原来的答案IntPtr.Zero打开了选项,并提供了必要的信息来帮助您做出决定。我正在添加来自docs 的另一个引用,其中讨论了何时不使用 null:

如果 hMod 参数为 NULL 并且 dwThreadId 参数为零或指定由另一个进程创建的线程的标识符,则可能会发生错误。

由于您使用 0 作为线程 ID(根据文档,这意味着“所有现有线程与调用线程在同一桌面上运行”),因此您不应使用 null 而应使用Marshal.GetHINSTANCE


我认为您应该通过 IntPtr.Zero 或Marshal.GetHINSTANCE(your current module)

根据这些文档,第三个参数 ( hMod) 是 -

A handle to the DLL containing the hook procedure pointed to by the lpfn parameter. The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.

Also as mentioned in this article ("Windows Hooks in the .NET Framework"),

The third argument should be the HINSTANCE handle of the DLL that contains the code for the filter function. Typically, this value is set to NULL for local hooks. Do not use the .NET null object, though; use the IntPtr.Zero expression, which is the correct counterpart for Win32 null handles. The HINSTANCE argument cannot be null for systemwide hooks, but must relate to the module that contains the hook code—typically an assembly. The Marshal.GetHINSTANCE static method will return the HINSTANCE for the specified .NET module.

Also, see this question.

于 2013-01-10T15:15:18.167 回答