SetWindowHookEx始终返回NULL

时间:2016-05-28 22:24:34

标签: c# c++ setwindowshookex

我正在尝试将CBT_HOOK设置为检测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);
    }
}

想要从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和Thread id(具有Hightest ThreadPriorityLevel的ProcessThread.Id),但SetHook总是返回0。

那么,我应该传递什么" threadID"到SetWindowHookEx?或问题还有其他问题吗?

P.S。我使用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"

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", SetLastError = true)]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool SetHook(uint hWnd);

[DllImport(@"C:\Users\..\dll.dll")]
[return: MarshalAs(UnmanagedType.I1)]
public static extern bool RemoveHook();

bool hook = false;

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

    var threadID = (uint)proc.Threads[0].Id;
    hook = SetHook(ThreadID); //This works, for example, for "notepad.exe" which has only one thread. May not work prorerly with other processes!

    if(hook)
      MessageBox.Show("Hooked!");
    else
      MessageBox.Show("Some error occured");
}

private void buttonRemoveHook_Click(object sender, EventArgs e)
{
    if (hook)
        RemoveHook();
}

screenshot of hooked notepad

0 个答案:

没有答案