全局钩子DLL仅在C#主窗口处于活动/前台状态时调用C#回调方法 我有一个C应用程序,它打开C++全局密钥钩子。dll全局侦听按键,并在按下某个键时调用主应用程序回调方法
dll钩子进程可以工作,只是当主应用程序不是活动屏幕时,它不调用回调函数,这在这种状态下是没有意义的。这有什么办法吗?我可能遗漏了什么 C#代码: C++全局键挂钩dll:全局钩子DLL仅在C#主窗口处于活动/前台状态时调用C#回调方法 我有一个C应用程序,它打开C++全局密钥钩子。dll全局侦听按键,并在按下某个键时调用主应用程序回调方法,c#,c++,multithreading,callback,hook,C#,C++,Multithreading,Callback,Hook,dll钩子进程可以工作,只是当主应用程序不是活动屏幕时,它不调用回调函数,这在这种状态下是没有意义的。这有什么办法吗?我可能遗漏了什么 C#代码: C++全局键挂钩dll: #include "pch.h" #include <stdio.h> #include <ctime> //these variables will be shared among all processes to which this dll is linked #pragma data_seg
#include "pch.h"
#include <stdio.h>
#include <ctime>
//these variables will be shared among all processes to which this dll is linked
#pragma data_seg("Shared")
//our hook handle which will be returned by calling SetWindowsHookEx function
HHOOK hkKey = NULL;
HINSTANCE hInstHookDll = NULL; //our global variable to store the instance of our DLL
#pragma data_seg() //end of our data segment
#pragma comment(linker,"/section:Shared,rws")
// Tell the compiler that Shared section can be read,write and shared
HWND pHWnd = NULL;
typedef void(__stdcall* PCallBack)(int points);
PCallBack g_pCallBack = NULL;
// used to register callback
extern "C" __declspec(dllexport) void __stdcall SetCallBack(PCallBack pCallBack)
{
g_pCallBack = pCallBack;
}
// call callbacak function
extern "C" __declspec(dllexport) void __stdcall PerformAction(int points)
{
if (g_pCallBack)
{
g_pCallBack(points);
}
}
//this is the hook procedure
__declspec(dllexport) LRESULT CALLBACK procCharMsg(int nCode, WPARAM wParam, LPARAM lParam)
{
//a pointer to hold the MSG structure that is passed as lParam
MSG* msg;
//to hold the character passed in the MSG structure's wParam
char charCode;
if (nCode >= 0 && nCode == HC_ACTION)
//if nCode is less than 0 or nCode
//is not HC_ACTION we will call CallNextHookEx
{
//lParam contains pointer to MSG structure.
msg = (MSG*)lParam;
if (msg->message == WM_CHAR)
{
charCode = msg->wParam;
if (IsCharLower(charCode))
//we check if the character pressed is a small letter
{
//if so, make it to capital letter
charCode -= 32;
msg->wParam = (WPARAM)charCode;
//overwrite the msg structure's wparam
//with our new value.
}
if (charCode == 'A') {
PerformAction(0); // Point Zero
}
else if (charCode == 'B') {
PerformAction(1); // Point One
}
else {
PerformAction(2); // Point Two
}
}
}
return CallNextHookEx(hkKey, nCode, wParam, lParam);
}
extern "C" __declspec(dllexport) void __stdcall SetHook()
{
if (hkKey == NULL)
hkKey = SetWindowsHookEx(WH_GETMESSAGE, procCharMsg, hInstHookDll, 0);
}
//remove the hook
extern "C" __declspec(dllexport) void __stdcall RemoveHook()
{
if (hkKey != NULL)
UnhookWindowsHookEx(hkKey);
hkKey = NULL;
}
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) {
switch (Reason)
{
case DLL_PROCESS_ATTACH:
//we initialize our variable with the value that is passed to us
hInstHookDll = (HINSTANCE)hDLL;
break;
default:
break;
}
return TRUE;
}
#包括“pch.h”
#包括
#包括
//这些变量将在链接此dll的所有进程之间共享
#pragma data_seg(“共享”)
//我们的钩子句柄,它将通过调用SetWindowsHookEx函数返回
HHOOK-hkKey=NULL;
HINSTANCE hInstHookDll=NULL//用于存储DLL实例的全局变量
#pragma data_seg()//数据段结束
#pragma注释(链接器,“/section:Shared,rws”)
//告诉编译器共享部分可以读、写和共享
HWND pHWnd=NULL;
typedef void(u stdcall*PCallBack)(整数点);
PCallBack g_PCallBack=NULL;
//用于注册回调
外部“C”\u declspec(dllexport)void\u stdcall SetCallBack(PCallBack PCallBack)
{
g_pCallBack=pCallBack;
}
//调用callbacak函数
外部“C”\uuuuu declspec(dllexport)无效\uuuuu stdcall性能(整数点)
{
if(g_pCallBack)
{
g_pCallBack(点);
}
}
//这是钩子程序
__declspec(dllexport)LRESULT回调procCharMsg(int-nCode、WPARAM-WPARAM、LPARAM-LPARAM)
{
//保存作为LPRAM传递的MSG结构的指针
味精*味精;
//保存在MSG结构的wParam中传递的字符
字符编码;
如果(nCode>=0&&nCode==HC\U动作)
//如果nCode小于0或nCode
//我们将调用CallNextHookEx,这不是HC_操作吗
{
//LPRAM包含指向MSG结构的指针。
msg=(msg*)LPRAM;
如果(消息->消息==WM\U字符)
{
charCode=msg->wParam;
if(IsCharLower(charCode))
//我们检查按下的字符是否为小写字母
{
//如果是,请使用大写字母
charCode-=32;
msg->wParam=(wParam)字符码;
//覆盖msg结构的wparam
//用我们的新价值观。
}
如果(charCode='A'){
性能(0);//零点
}
else if(charCode=='B'){
性能(1);//第一点
}
否则{
性能(2);//第二点
}
}
}
返回CallNextHookEx(hkKey、nCode、wParam、lParam);
}
外部“C”uuu declspec(dllexport)void uuu stdcall SetHook()
{
如果(hkKey==NULL)
hkKey=SetWindowsHookEx(WH_GETMESSAGE,procCharMsg,hInstHookDll,0);
}
//拆下挂钩
外部“C”uu declspec(dllexport)void uu stdcall RemoveHook()
{
如果(hkKey!=NULL)
Unhookwindowshookx(香港键);
hkKey=NULL;
}
INT APIENTRY DllMain(HMODULE hDLL,DWORD原因,LPVOID保留){
切换(原因)
{
案例DLL\u进程\u附加:
//我们用传递给我们的值初始化变量
hInstHookDll=(HINSTANCE)hDLL;
打破
违约:
打破
}
返回TRUE;
}
编辑:我将方法更改为指向主窗口的共享HWND指针。然后,只需向该HWND发送/发布消息,我就可以通过WndProc接收信息。每个正在运行的进程都会加载一个全局钩子,这意味着每个进程都会加载自己的DLL副本 钩子DLL通过将
HHOOK
句柄存储在一个共享数据段中以供所有进程共享来说明这一点。但是g_pCallBack
变量未存储在该段中,因此不会被共享。只有实际调用SetCallback()
的原始进程才会分配其g_pCallBack
,因此只有该进程中的键盘活动才会报告给回调
您也不能将g_pCallBack
存储在共享段中,因为不能跨进程边界调用原始函数指针。您需要使用诸如COM或RPC之类的进程间通信框架来实现这一点
一个简单的解决方案是将
g_pCallBack
替换为存储在共享段中的HWND
,然后加载到每个进程中的钩子可以在需要时将窗口消息发布到HWND
。C#应用程序可以分配一个窗口来接收这些消息,并将该窗口提供给其DLL副本以存储在共享段中。或者,如果您想继续使用委托
,则让SetHook()
create is ownHWND
,然后让窗口处理程序在指定的情况下调用委托。在每个正在运行的进程中加载一个全局钩子,这意味着每个进程都会加载自己的DLL副本
钩子DLL通过将HHOOK
句柄存储在一个共享数据段中以供所有进程共享来说明这一点。但是g_pCallBack
变量未存储在该段中,因此不会被共享。只有实际调用SetCallback()
的原始进程才会分配其g_pCallBack
,因此只有该进程中的键盘活动才会报告给回调
您也不能将g_pCallBack
存储在共享段中,因为不能跨进程边界调用原始函数指针。您需要使用诸如COM或RPC之类的进程间通信框架来实现这一点
一个简单的解决方案是将g_pCallBack
替换为存储在共享段中的HWND
,然后加载到每个进程中的钩子可以将窗口消息发布到HWND
#include "pch.h"
#include <stdio.h>
#include <ctime>
//these variables will be shared among all processes to which this dll is linked
#pragma data_seg("Shared")
//our hook handle which will be returned by calling SetWindowsHookEx function
HHOOK hkKey = NULL;
HINSTANCE hInstHookDll = NULL; //our global variable to store the instance of our DLL
#pragma data_seg() //end of our data segment
#pragma comment(linker,"/section:Shared,rws")
// Tell the compiler that Shared section can be read,write and shared
HWND pHWnd = NULL;
typedef void(__stdcall* PCallBack)(int points);
PCallBack g_pCallBack = NULL;
// used to register callback
extern "C" __declspec(dllexport) void __stdcall SetCallBack(PCallBack pCallBack)
{
g_pCallBack = pCallBack;
}
// call callbacak function
extern "C" __declspec(dllexport) void __stdcall PerformAction(int points)
{
if (g_pCallBack)
{
g_pCallBack(points);
}
}
//this is the hook procedure
__declspec(dllexport) LRESULT CALLBACK procCharMsg(int nCode, WPARAM wParam, LPARAM lParam)
{
//a pointer to hold the MSG structure that is passed as lParam
MSG* msg;
//to hold the character passed in the MSG structure's wParam
char charCode;
if (nCode >= 0 && nCode == HC_ACTION)
//if nCode is less than 0 or nCode
//is not HC_ACTION we will call CallNextHookEx
{
//lParam contains pointer to MSG structure.
msg = (MSG*)lParam;
if (msg->message == WM_CHAR)
{
charCode = msg->wParam;
if (IsCharLower(charCode))
//we check if the character pressed is a small letter
{
//if so, make it to capital letter
charCode -= 32;
msg->wParam = (WPARAM)charCode;
//overwrite the msg structure's wparam
//with our new value.
}
if (charCode == 'A') {
PerformAction(0); // Point Zero
}
else if (charCode == 'B') {
PerformAction(1); // Point One
}
else {
PerformAction(2); // Point Two
}
}
}
return CallNextHookEx(hkKey, nCode, wParam, lParam);
}
extern "C" __declspec(dllexport) void __stdcall SetHook()
{
if (hkKey == NULL)
hkKey = SetWindowsHookEx(WH_GETMESSAGE, procCharMsg, hInstHookDll, 0);
}
//remove the hook
extern "C" __declspec(dllexport) void __stdcall RemoveHook()
{
if (hkKey != NULL)
UnhookWindowsHookEx(hkKey);
hkKey = NULL;
}
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) {
switch (Reason)
{
case DLL_PROCESS_ATTACH:
//we initialize our variable with the value that is passed to us
hInstHookDll = (HINSTANCE)hDLL;
break;
default:
break;
}
return TRUE;
}