【问题标题】:Error when using SetWindowsHookEx in Windows XP, but not in Windows 7在 Windows XP 中使用 SetWindowsHookEx 时出错,但在 Windows 7 中没有
【发布时间】:2012-05-17 23:44:53
【问题描述】:

我开发了一个使用全局键盘/鼠标挂钩的应用程序。它在 Windows 7 中完美运行,但在 Windows XP 中却不行。

当我在 Windows XP 中调用 SetWindowsHookEx 时,我收到错误代码 1428

int MouseLowLevel   = 14
int code = SetWindowsHookEx(MouseLowLevel,
                 MouseHookProc,
                 IntPtr.Zero,
                 0);

private IntPtr MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam) {}

【问题讨论】:

    标签: c# winapi hook keyboard-hook setwindowshookex


    【解决方案1】:

    很好奇这段代码在 Win7 上不会失败,但我当然从未尝试过。但这是正确的行为,看起来他们改进了它。 SetWindowsHookEx() 的参数验证需要有效的非零第三或第四参数。错误代码描述性很强,来自 WinError.h:

    //
    // MessageId: ERROR_HOOK_NEEDS_HMOD
    //
    // MessageText:
    //
    // Cannot set nonlocal hook without a module handle.
    //
    #define ERROR_HOOK_NEEDS_HMOD            1428L
    

    任何模块句柄都可以,因为它实际上并不用于低级挂钩,不需要注入 DLL 来使它们工作。 .NET 4 需要谨慎选择一个,因为它的 CLR 不再为纯托管程序集伪造模块句柄。一个很好的使用方法是你从 pinvoking LoadLibrary("user32.dll") 中得到的那个,因为它总是已经加载了。您不必调用 FreeLibrary()。

    你需要这个声明来调用 LoadLibrary:

    [DllImport("kernel32", SetLastError=true, CharSet = CharSet.Auto)]
    private static extern IntPtr LoadLibrary(string fileName);
    

    【讨论】:

    • 非常感谢您的出色回复。现在它适用于 Windows 7 和 XP。
    • 您的代码中还有另一个错误,SetWindowsHookEx() 的返回类型是 IntPtr,而不是 int。
    • 哎呀,我在简化代码时犯了一些错误。在实际代码中,我使用了一个继承自 SafeHandleZeroOrMinusOneIsInvalid 的类。但是当我附上代码时,我不想太多细节。不过还是谢谢 :-)
    • 我原以为GetModuleHandle("kernel32.dll") 会是一个更明显的选择。
    • 最小意外原则,SetWindowsHookEx 需要使用 user32.dll 的 pinvoke 声明
    猜你喜欢
    • 2012-06-09
    • 2012-07-17
    • 1970-01-01
    • 2011-03-21
    • 2014-02-06
    • 1970-01-01
    • 2013-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多