我正在尝试将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();
}