C# SetWindowHookEx始终返回NULL

C# SetWindowHookEx始终返回NULL,c#,c++,setwindowshookex,C#,C++,Setwindowshookex,我试图设置CBT_钩子来检测诸如WM_DESTROY、WM_CLOSE、WM_WINDOWPOSCHANGING、WM_CREATE等消息,所以它应该是非全局钩子 我用C++编写了简单的DLL: DllMain.cpp: #include "stdafx.h" HINSTANCE hInst; BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call,

我试图设置CBT_钩子来检测诸如WM_DESTROY、WM_CLOSE、WM_WINDOWPOSCHANGING、WM_CREATE等消息,所以它应该是非全局钩子

我用C++编写了简单的DLL:

DllMain.cpp:

#include "stdafx.h"

HINSTANCE hInst;

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        if (hInst == NULL)
            hInst = hModule;

        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
dll.cpp:

#include "stdafx.h"

HWND hWnd;
HHOOK CBTHookID;

static LRESULT CALLBACK CBTHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    MessageBox(NULL, TEXT("inside hook proc!"), TEXT(""), MB_OK);
    return CallNextHookEx(CBTHookID, nCode, wParam, lParam);
}

extern "C" {
    __declspec(dllexport) bool SetHook(DWORD threadID, HWND _hWnd)
    {
        hWnd = _hWnd;
        CBTHookID = SetWindowsHookEx(WH_CBT, CBTHookProc, 0, threadID);

        return CBTHookID ? true : false;
    }
}

extern "C" {
    __declspec(dllexport) void RemoveHook()
    {
        UnhookWindowsHookEx(CBTHookID);
        MessageBox(NULL, TEXT("unhooked"), TEXT("ok"), MB_OK);
    }
}
#include "stdafx.h"

extern HINSTANCE hInst; // A handle to the DLL module

static LRESULT CALLBACK CBTHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HCBT_ACTIVATE)
    {
        MessageBox(NULL, TEXT("HCBT_ACTIVATE"), TEXT("inside hook"), MB_OK);
    }

    return CallNextHookEx(NULL, nCode, wParam, lParam); //according to MSDN, first parameter is ignored
}

extern "C" 
{
    __declspec(dllexport) bool SetHook(DWORD threadID)
    {
        CBTHookID = SetWindowsHookEx(WH_CBT, CBTHookProc, hInst , threadID);
        return CBTHookID != 0;
    }
}

extern "C" 
{
    __declspec(dllexport) bool RemoveHook()
    {
        int removed = UnhookWindowsHookEx(CBTHookID);
        MessageBox(NULL, TEXT("unhooked"), TEXT(""), MB_OK);
        return removed != 0;
    }
}
要从c#应用程序设置钩子:

[DllImport(@"C:\Users\..\dll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr SetHook(IntPtr hWnd);

[DllImport(@"C:\Users\..\dll.dll")]
public static extern bool RemoveHook(IntPtr hHook);

IntPtr hook = IntPtr.Zero;

private void buttonSetHook_Click(object sender, EventArgs e)
{
     // proc - the process I want to set hook to

     hook = SetHook((IntPtr)proc.MainWindowHandle);
     MessageBox.Show(hook.ToString());
}
钩子总是0。我已尝试为此进程传递具有最高优先级的proc.hande和线程id(具有最高ThreadPriorityLevel的ProcessThread.id),但SetHook始终返回0

那么,我应该将什么作为“threadID”传递给SetWindowHookEx?还是问题出在别人身上

另外,我使用VisualStudio,对于这个项目,我以管理员的身份运行它,操作系统是windows 10

编辑: 在评论员的帮助下,我现在找到了可行的解决方案:

DllMain.cpp

// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"

HINSTANCE hInst; // A handle to the DLL module

BOOL APIENTRY DllMain( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        if (hInst == NULL)
            hInst = hModule;
        break;

    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
dll.cpp:

#include "stdafx.h"

HWND hWnd;
HHOOK CBTHookID;

static LRESULT CALLBACK CBTHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    MessageBox(NULL, TEXT("inside hook proc!"), TEXT(""), MB_OK);
    return CallNextHookEx(CBTHookID, nCode, wParam, lParam);
}

extern "C" {
    __declspec(dllexport) bool SetHook(DWORD threadID, HWND _hWnd)
    {
        hWnd = _hWnd;
        CBTHookID = SetWindowsHookEx(WH_CBT, CBTHookProc, 0, threadID);

        return CBTHookID ? true : false;
    }
}

extern "C" {
    __declspec(dllexport) void RemoveHook()
    {
        UnhookWindowsHookEx(CBTHookID);
        MessageBox(NULL, TEXT("unhooked"), TEXT("ok"), MB_OK);
    }
}
#include "stdafx.h"

extern HINSTANCE hInst; // A handle to the DLL module

static LRESULT CALLBACK CBTHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HCBT_ACTIVATE)
    {
        MessageBox(NULL, TEXT("HCBT_ACTIVATE"), TEXT("inside hook"), MB_OK);
    }

    return CallNextHookEx(NULL, nCode, wParam, lParam); //according to MSDN, first parameter is ignored
}

extern "C" 
{
    __declspec(dllexport) bool SetHook(DWORD threadID)
    {
        CBTHookID = SetWindowsHookEx(WH_CBT, CBTHookProc, hInst , threadID);
        return CBTHookID != 0;
    }
}

extern "C" 
{
    __declspec(dllexport) bool RemoveHook()
    {
        int removed = UnhookWindowsHookEx(CBTHookID);
        MessageBox(NULL, TEXT("unhooked"), TEXT(""), MB_OK);
        return removed != 0;
    }
}
和c#代码:


“要获取扩展错误信息,请调用GetLastError。”返回什么?
SetHook
接受两个参数,但只传递一个。这似乎是个坏主意。@AlanStokes谢谢你的回答!我从SetHook参数中删除了hWnd,因为我从未在任何地方使用过它。现在,如果我传递proc.handle、proc.mainWindowHandle或proc.Id GetLastError返回错误代码87 error\u INVALID\u参数(该参数不正确),如果我传递具有要设置钩子的进程的最高优先级的线程Id,GetLastError返回1428 error\u hook\u NEEDS\u HMOD(无法设置没有模块句柄的非本地钩子)。我想这就是问题所在。建议您的C#函数导入已关闭-请尝试
uint
获取
DWORD
参数。你的退货类型肯定是一团糟。为什么要为
bool
函数(
SetHook
)指定
IntPtr
返回值,为
void
函数(
RemoveHook
)指定
bool
)返回值?需要将DLL句柄传递到
setWindowshookex
“要获取扩展的错误信息,请调用GetLastError。”返回什么?
SetHook
接受两个参数,但只传递一个。这似乎是个坏主意。@AlanStokes谢谢你的回答!我从SetHook参数中删除了hWnd,因为我从未在任何地方使用过它。现在,如果我传递proc.handle、proc.mainWindowHandle或proc.Id GetLastError返回错误代码87 error\u INVALID\u参数(该参数不正确),如果我传递具有要设置钩子的进程的最高优先级的线程Id,GetLastError返回1428 error\u hook\u NEEDS\u HMOD(无法设置没有模块句柄的非本地钩子)。我想这就是问题所在。建议您的C#函数导入已关闭-请尝试
uint
获取
DWORD
参数。你的退货类型肯定是一团糟。为什么要为
bool
函数(
SetHook
)指定
IntPtr
返回值,为
void
函数(
RemoveHook
)指定
bool
)?需要将DLL的句柄传递给
setWindowshookex