为什么使用LoadLibrary而不是只获取程序的BaseAddress

时间:2013-01-10 14:46:57

标签: c# winapi native-methods

...主观HA

好吧所以我一直在寻找一个合理的解决方案来捕获多次击键并且使用相同的东西(键盘钩子)的一些解决方案。一个soltuion使用本机调用来按名称获取进程的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);

比另一个更安全吗?我是在做一个致命的错误而不是表现出来吗?

2 个答案:

答案 0 :(得分:3)

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

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

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

怪癖是SetWindowsHookEx()检查你是否传递了一个有效的模块句柄,但实际上并没有将它用于低级别的钩子。所以你传递的任何有效句柄都可以。这个怪癖在Windows 7 SP1顺便修复,它不再执行检查。

答案 1 :(得分:0)

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

  

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

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


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

根据these docs,第三个参数(hMod)是 -

  

DLL的句柄,包含指向的钩子过程   lpfn参数。如果是,则必须将hMod参数设置为NULL   dwThreadId参数指定当前进程创建的线程   和如果钩子程序在与之关联的代码中   当前进程。

另外as mentioned in this article ("Windows Hooks in the .NET Framework")

  

第三个参数应该是包含过滤函数代码的DLL的HINSTANCE句柄。通常,对于本地挂钩,此值设置为NULL。但是,不要使用.NET null对象;使用IntPtr.Zero表达式,它是Win32 null句柄的正确对应表达式。 对于系统范围的挂钩,HINSTANCE参数不能为null,但必须与包含挂钩代码的模块相关 - 通常是程序集。 Marshal.GetHINSTANCE静态方法将返回指定.NET模块的HINSTANCE。

另请参阅this question