SetWindowsHookEx 不适用于线程 ID

Posted

技术标签:

【中文标题】SetWindowsHookEx 不适用于线程 ID【英文标题】:SetWindowsHookEx doesn't work with thread Id 【发布时间】:2011-08-28 11:04:04 【问题描述】:

您好,提前感谢任何愿意提供帮助的人。 我正在尝试设置一个 CBT windows 挂钩,当我在全局设置它时效果很好,但每当我尝试将它附加到单个线程时都会失败。据我所知,我在做所有事情: - 我从一个非托管的 dll 中暴露了钩子过程 - 我的应用程序、dll 和线程的进程都是 32 位的 - 我使用的线程ID是正确的(用spy++确认)

当我试图只从 c++ 代码中挂钩一个线程时,我设法做到了……你能只从非托管代码中挂钩一个线程吗?

这是我的代码:

[DllImport( "user32.dll", SetLastError = true )]
    static extern IntPtr SetWindowsHookEx ( int hookType, UIntPtr lpfn, IntPtr hMod, uint dwThreadId );

[DllImport( "kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true )]
    public static extern UIntPtr GetProcAddress ( IntPtr hModule, string procName );

[DllImport( "kernel32", SetLastError = true, CharSet = CharSet.Unicode )]
    public static extern IntPtr LoadLibrary ( string libraryName );

const int WH_CBT = 5;

    void SetHook ()
    
        IntPtr dll = LoadLibrary( LIBRARY );
        UIntPtr proc = GetProcAddress( dll, PROC );
        uint threadId = GetAppWindowThreadId();
         //assume that the threadId of the external window is correct, as I said I verified with spy++
         //and assume that dll and proc both get correct values
        IntPtr hookAddress = SetWindowsHookEx( WH_CBT , proc, dll, threadId );
         //hookAddress is 0
    

【问题讨论】:

Marshal.GetLastWin32Error 有什么要说的? 【参考方案1】:
[DllImport( "user32.dll", SetLastError = true )]
static extern IntPtr SetWindowsHookEx ( int hookType, UIntPtr lpfn, 
                                        IntPtr hMod, ulong dwThreadId );

那个声明是错误的。最后一个参数 (dwThreadId) 的类型是 DWORD,在 C# 中是一个 uint。

奇怪的是,您没有收到 PInvokeStackImbalance 调试器警告。这表明您在 64 位操作系统上运行。这增加了几种额外的故障模式,您注入的 DLL 必须包含编译为您的进程和要挂钩的进程的正确位数的非托管代码。根据需要设置项目的平台目标。您的代码缺少所有错误检查,因此您不知道为什么它不起作用,请确保在收到失败返回码时抛出 new Win32Exception()。

【讨论】:

起初它是 uint 而不是 ulong,它也不适用于 uint 没有记录表明 winapi 函数失败并且 not 设置 GetLastError() 返回值的案例。在没有代码可看也没有办法测试的情况下,除了这个问题,我几乎无能为力。

以上是关于SetWindowsHookEx 不适用于线程 ID的主要内容,如果未能解决你的问题,请参考以下文章

用于 DeviceIOControl 的 SetWindowsHookEx,要使用啥 hookid?

EasyHook 不适用于其他线程

队列不适用于线程?

time.sleep 不适用于多线程

ThreadPoolTask Scheduler不适用于线程池

多个摄像头馈送不适用于 PyQt5 线程: