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

本文关键字:获取 程序 BaseAddress LoadLibrary 为什么 | 更新日期: 2023-09-27 17:51:16

主观。。。HA

好吧,我一直在互联网上寻找一个合理的解决方案来捕获多个击键,并遇到了一些使用相同功能(键盘挂钩(的解决方案。一个解决方案使用本机调用按名称获取进程的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);

一个比另一个安全吗?我是不是犯了一个致命的错误,没有显示它的头部?

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

SetWindowsHookEx((需要一个有效的模块句柄。它使用它来计算需要将什么DLL注入到其他进程中才能使钩子工作。

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

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

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

EDIT:我最初的回答保留了IntPtr.Zero选项,并提供了必要的信息来帮助您做出决定。我添加了文档中的另一句话,其中讨论了何时不使用null:

如果hMod参数为NULL并且dwThreadId参数为零或指定由创建的线程的标识符另一个过程。

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


我认为你应该通过其中一个IntPtr。零或Marshal.GetHINSTANCE(your current module)

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

DLL的句柄,该句柄包含由lpfn参数。如果dwThreadId参数指定由当前进程创建的线程如果钩子过程在与当前过程

正如本文所提到的(".NET框架中的Windows挂钩"(,

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

另请参阅此问题。