如何从另一个进程中解除全局钩子? 这是我现在的设置:我有一个C++ DLL,它把它的一个函数全局钩住了计算机上运行的每个进程。挂接是在DLLMain中使用setWindowshookxwinapi函数完成的,我正在挂接WH\u CBT和WH\u SHELL事件。我还有一个C#应用程序,它用p/invoke(LoadLibrary())加载DLL,从而触发从DLLMain安装挂钩。DLL中的处理程序通过命名管道向C#app发送事件信息 基于我在上面所读到的,这些事件将在目标进程的线程上处理,并且必须由独立的C++ DLL安装(不像WHMouthyll和WHKEKBOARADLL,任何应用都可以安装)。

如何从另一个进程中解除全局钩子? 这是我现在的设置:我有一个C++ DLL,它把它的一个函数全局钩住了计算机上运行的每个进程。挂接是在DLLMain中使用setWindowshookxwinapi函数完成的,我正在挂接WH\u CBT和WH\u SHELL事件。我还有一个C#应用程序,它用p/invoke(LoadLibrary())加载DLL,从而触发从DLLMain安装挂钩。DLL中的处理程序通过命名管道向C#app发送事件信息 基于我在上面所读到的,这些事件将在目标进程的线程上处理,并且必须由独立的C++ DLL安装(不像WHMouthyll和WHKEKBOARADLL,任何应用都可以安装)。,c++,winapi,hook,C++,Winapi,Hook,到目前为止一切正常;托管应用程序正在按其应接收的方式接收数据。当我关闭应用程序时,问题出现了,因为处理程序仍然挂接,因此DLL文件正在使用中,无法删除 由于处理程序没有在我的应用程序中运行,而是注入到我计算机上运行的其他进程中,C#app不能简单地调用UnhookWindowsHookEx或freebrary,因为事件处理程序的指针属于其他进程 问题: 如何从托管应用程序触发解除挂钩例程,以确保DLL不再被任何进程使用 以下是我尝试过的: 我能想到的唯一解决方案是创建一个退出事件(使用Creat

到目前为止一切正常;托管应用程序正在按其应接收的方式接收数据。当我关闭应用程序时,问题出现了,因为处理程序仍然挂接,因此DLL文件正在使用中,无法删除

由于处理程序没有在我的应用程序中运行,而是注入到我计算机上运行的其他进程中,C#app不能简单地调用
UnhookWindowsHookEx
freebrary
,因为事件处理程序的指针属于其他进程

问题:

如何从托管应用程序触发解除挂钩例程,以确保DLL不再被任何进程使用

以下是我尝试过的:

我能想到的唯一解决方案是创建一个退出事件(使用
CreateEvent
),每当处理程序接收到
WH\u CBT
WH\u SHELL
消息时,它都会检查是否设置了退出事件,在这种情况下,它会将自身从它所属的进程中解扣并在处理消息之前返回

这种方法的问题是,在我关闭应用程序并卸载DLL之后,我必须等待,直到其余进程至少收到一次WH事件,这样属于它们的处理程序就可以自行解除挂钩

以下是DLL的代码:

#include <windows.h>
#include <sstream>

HANDLE hTERM;
HHOOK hCBT;
HHOOK hShell;

void __declspec(dllexport) InstallHooks(HMODULE h);
void __declspec(dllexport) RemoveHooks();

int Continue()
{
    return WAIT_TIMEOUT == WaitForSingleObject(hTERM, 0);
}

LRESULT FAR PASCAL _cbtProc(int c, WPARAM w, LPARAM l)
{
    if (!Continue()) { RemoveHooks(); return 0; }   
    // Handling the message ...
    return CallNextHookEx(0, c, w, l);
}

LRESULT FAR PASCAL _shellProc(int c, WPARAM w, LPARAM l)
{
    if (!Continue()) { RemoveHooks(); return 0; }
    // Handling the message ...
    return CallNextHookEx(0, c, w, l);
}

void InstallHooks(HMODULE h)
{
    hTERM = OpenEvent(EVENT_ALL_ACCESS, 0, __TEXT("{0C3ED513-F38C-4996-8130-F9A3C93D890B}"));
    if (!Continue())
        return;
    hCBT = SetWindowsHookEx(WH_CBT, _cbtProc, h, 0);
    hShell = SetWindowsHookEx(WH_SHELL, _shellProc, h, 0);
}

void RemoveHooks()
{
    UnhookWindowsHookEx(hCBT);
    UnhookWindowsHookEx(hShell);
    if (hTERM) CloseHandle(hTERM); hTERM = 0;
}

int FAR PASCAL DllMain(HMODULE h, DWORD r, void* p)
{
    switch (r)
    {
        case DLL_PROCESS_ATTACH: InstallHooks(h); break;
        case DLL_PROCESS_DETACH: RemoveHooks(); break;
        default: break;
    }
    return 1;
}
#包括
#包括
处理hTERM;
HHOOK-hCBT;
HHOOK-hShell;
void uu declspec(dllexport)安装挂钩(HMODULE h);
void uu declspec(dllexport)RemoveHooks();
int Continue()
{
返回WAIT_TIMEOUT==WaitForSingleObject(hTERM,0);
}
LRESULT远帕斯卡(int c,WPARAM w,LPARAM l)
{
如果(!Continue()){RemoveHooks();返回0;}
//正在处理消息。。。
返回CallNextHookEx(0,c,w,l);
}
LRESULT远帕斯卡(int c,WPARAM w,LPARAM l)
{
如果(!Continue()){RemoveHooks();返回0;}
//正在处理消息。。。
返回CallNextHookEx(0,c,w,l);
}
无效安装挂钩(HM模块h)
{
hTERM=OpenEvent(事件所有访问,0,文本({0C3ED513-F38C-4996-8130-F9A3C93D890B}));
如果(!Continue())
返回;
hCBT=SetWindowsHookEx(WH_CBT,_cbtProc,h,0);
hShell=SetWindowsHookEx(WH_SHELL,_shellProc,h,0);
}
void RemoveHooks()
{
UnhookWindowsHookEx(hCBT);
UnhookWindowsHookEx(hShell);
if(hTERM)CloseHandle(hTERM);hTERM=0;
}
法尔帕斯卡·德尔梅因(h模块h,DWORD r,void*p)
{
开关(r)
{
案例DLL_进程_附加:安装挂钩(h);中断;
案例DLL_进程_分离:RemoveHooks();中断;
默认:中断;
}
返回1;
}
托管C#app的源代码没有什么特别之处,因为它所做的唯一事情是在启动时调用
LoadLibrary
,处理来自管道的消息,并在需要时使用另一个p/invoke调用设置退出事件。

“挂钩在DLLMain中完成”-那是处理这件事的完全错误的地方

每次将DLL加载到新进程中时,它都会安装一组新的Shell/CBT挂钩,这是您不希望/不需要的。你只需要一套

正确的解决方案是让DLL导出其
InstallHooks()
removehoks()
函数,然后在将DLL加载到自身后,只让C应用程序调用它们。这一组钩子将根据需要将DLL加载到所有正在运行的进程中,而无需每次调用
SetWindowsHookEx()

另外,不要从钩子回调本身内部调用
unhookwindowshookx()
。在C#app退出之前,它应该调用
RemoveHooks()
,然后在调用
unhookwindowshookx()
之前发出
hTerm
事件的信号。如果
Continue()。但是不要跳过调用
CallNextHookEx()
,即使
Continue()
返回false,因为其他应用程序可能安装了其他挂钩,并且您不想破坏它们

请尝试类似以下内容:

#include <windows.h>

HMODULE hModule = NULL;
HANDLE hTERM = NULL;
HHOOK hCBT = NULL;
HHOOK hShell = NULL;

static bool Continue()
{
    return (WAIT_TIMEOUT == WaitForSingleObject(hTERM, 0));
}

LRESULT CALLBACK _cbtProc(int code, WPARAM wParam, LPARAM lParam)
{
    if (Continue()) {
        // Handle the message ...
    }
    return CallNextHookEx(NULL, code, wParam, lParam);
}

LRESULT CALLBACK _shellProc(int code, WPARAM wParam, LPARAM lParam)
{
    if (Continue()) {
        // Handle the message ...
    }
    return CallNextHookEx(NULL, code, wParam, lParam);
}

__declspec(dllexport) BOOL WINAPI InstallHooks()
{
    if (!Continue())
        return FALSE;

    if (!hCBT)
        hCBT = SetWindowsHookEx(WH_CBT, _cbtProc, hModule, 0);

    if (!hShell)
        hShell = SetWindowsHookEx(WH_SHELL, _shellProc, hModule, 0);

    return ((hCBT) && (hShell)) ? TRUE : FALSE;
}

__declspec(dllexport) void WINAPI RemoveHooks()
{
    if (hTERM)
        SetEvent(hTERM);

    if (hCBT) {
        UnhookWindowsHookEx(hCBT);
        hCBT = NULL;
    }

    if (hShell) {
        UnhookWindowsHookEx(hShell);
        hShell = NULL;
    }
}

BOOL WINAPI DllMain(HMODULE hinstDLL, DWORD fdwReason, void* lpvReserved)
{
    hModule = hinstDLL;

    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            hTERM = CreateEvent(NULL, TRUE, FALSE, TEXT("{0C3ED513-F38C-4996-8130-F9A3C93D890B}"));
            if (!hTERM) return FALSE;
            break;

        case DLL_PROCESS_DETACH:
            if (hTERM) {
                CloseHandle(hTERM);
                hTERM = NULL;
            }
            break;
    }

    return TRUE;
}
#包括
HMODULE HMODULE=NULL;
句柄hTERM=NULL;
HHOOK-hCBT=NULL;
HHOOK-hShell=NULL;
静态bool Continue()
{
返回(WAIT_TIMEOUT==WaitForSingleObject(hTERM,0));
}
LRESULT回调_cbtProc(int代码、WPARAM WPARAM、LPARAM LPARAM)
{
如果(Continue()){
//处理消息。。。
}
返回CallNextHookEx(NULL、code、wParam、lParam);
}
LRESULT回调_shellProc(int代码、WPARAM WPARAM、LPARAM LPARAM)
{
如果(Continue()){
//处理消息。。。
}
返回CallNextHookEx(NULL、code、wParam、lParam);
}
__declspec(dllexport)BOOL WINAPI InstallHooks()
{
如果(!Continue())
返回FALSE;
如果(!hCBT)
hCBT=SetWindowsHookEx(WH_CBT,_cbtProc,hModule,0);
如果(!hShell)
hShell=SetWindowsHookEx(WH_SHELL,_shellProc,hModule,0);
返回((hCBT)和(hShell))?真:假;
}
__declspec(dllexport)void WINAPI RemoveHooks()
{
if(hTERM)
SetEvent(hTERM);
if(hCBT){
UnhookWi