0

我试图捕捉创建/销毁另一个应用程序的指定窗口的事件。为此我设置了WM_SHELLHOOK.

这是我的 WPF 应用程序中的简化代码:

public delegate IntPtr ProcDelegate(int hookCode, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(
    int hookId, ProcDelegate handler, IntPtr hInstance, uint threadId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);

private void buttonClick(object sender, RoutedEventArgs e)
{
    IntPtr hookHandler;

    using (Process curProcess = Process.GetCurrentProcess())
    using (ProcessModule curModule = curProcess.MainModule)
    {
        var moduleHandle = GetModuleHandle(curModule.ModuleName);
        hookHandler = SetWindowsHookEx(
            10 /*WH_SHELL*/, shellHookHandler, moduleHandle, 0);
    }

    if (hookHandler == IntPtr.Zero)
    {
        // Get here error 1428 (ERROR_HOOK_NEEDS_HMOD) -
        // "Cannot set nonlocal hook without a module handle."
        throw new Exception(Marshal.GetLastWin32Error().ToString());
    }
}

private IntPtr shellHookHandler(int hookCode, IntPtr wParam, IntPtr lParam)
{
    // Some code...
    return IntPtr.Zero;
}

问题是SetWindowsHookEx总是返回 0 并且最后一个错误是

1428 (ERROR_HOOK_NEEDS_HMOD) 不能在没有模块句柄的情况下设置非本地挂钩。

我看过另一个相关的问题。当我为鼠标、键盘等设置挂钩时 - 一切正常。

请指出我如何解决这个错误。谢谢。

4

1 回答 1

1

钩子的MSDN 文档说“如果应用程序为不同应用程序的线程安装钩子过程,则该过程必须在 DLL 中。”

这是因为您的 DLL 被加载到其他应用程序的地址空间中;然后,您需要找到某种机制(例如,内存映射文件)将信息传递给您的主应用程序。

然而,与大多数文档(这里提到)相反,键盘和鼠标钩子在没有 DLL 的情况下工作。这就是他们为你工作的原因。

于 2012-01-28T22:21:54.317 回答