全局钩子DLL仅在C#主窗口处于活动/前台状态时调用C#回调方法 我有一个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

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("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 own
HWND
,然后让窗口处理程序在指定的情况下调用委托。

在每个正在运行的进程中加载一个全局钩子,这意味着每个进程都会加载自己的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;
 }