c++实现dll框架

这是一段可以实现监控Windows事件的dll代码,使用VS2022选择C++ 应用程序扩展创建之后只需要修改 dllmain.cpp 的代码即可,无需其它任何配置,使用 release x64 build之后就可以被其它应用程序调用


#include "pch.h"

#include <windows.h>

#include <string>

//基础C++的dll代码框架

// 共享内存区定义

//将 g_hMainWnd 和 g_hEventHook 放在共享内存区

//RWS 标志表示该段具有 Read/Write/Shared 属性,确保多进程可访问同一内存区域

//g_hMainWnd 是主窗口的句柄,用于接收事件通知

//g_hEventHook 是事件钩子的句柄,用于监听窗口事件

#pragma data_seg(".SHARED")

HWND g_hMainWnd = NULL;

HWINEVENTHOOK g_hEventHook = NULL;

#pragma data_seg()

#pragma comment(linker, "/SECTION:.SHARED,RWS")

//事件处理函数,是一个回调函数,在事件发生时被调用,需要导出为C风格的函数

//参数说明:

// hWinEventHook: 事件钩子的句柄

// event: 事件类型

// hwnd: 事件发生的窗口句柄

// idObject: 事件对象的ID

// idChild: 事件子对象的ID

// dwEventThread: 事件发生的线程ID

// dwmsEventTime: 事件发生的时间戳

extern "C" __declspec(dllexport)

void CALLBACK WinEventProc(

    HWINEVENTHOOK hWinEventHook,

    DWORD event,

    HWND hwnd,

    LONG idObject,

    LONG idChild,

    DWORD dwEventThread,

    DWORD dwmsEventTime)

{

//IsWindow是一个API函数,用于检查指定的窗口句柄是否有效,必须在调用startMonitoring函数中传递窗口句柄,否则就直接返回

    if (!IsWindow(g_hMainWnd)) {

        return;

    }

    //如果没有标题就直接退出...

    wchar_t buf[256] = { 0 };

    if (!GetWindowTextW(hwnd, buf, _countof(buf))) {

        return;

    }

//这里创建一个 COPYDATASTRUCT 结构体,用于发送窗口标题到主程序

//这个结构体包含三个成员:

// dwData: 用于标识数据类型,这里使用事件类型

// cbData: 数据的大小,这里使用窗口标题的长度

// lpData: 指向数据的指针,这里使用窗口标题的缓冲区

    COPYDATASTRUCT cds = { 0 };

    cds.dwData = event;

    cds.cbData = (wcslen(buf) + 1) * sizeof(wchar_t);

    cds.lpData = buf;

    // 调试输出标题(可选)

    //OutputDebugStringW(L"窗口标题: ");

    //OutputDebugStringW(buf);

    //发送窗口标题到主程序(有些事件并没有)

    if (!SendMessageW(g_hMainWnd, WM_COPYDATA, 0, (LPARAM)&cds)) {

        DWORD err = GetLastError();

        wchar_t msg[64];

        swprintf(msg, _countof(msg), L"消息发送失败: %d", err);

        //OutputDebugStringW(msg);

    }

}

//导出函数,用于开始监控窗口事件

//参数说明:

// hCallbackWnd: 主窗口的句柄,用于接收事件通知,如果不需要接收事件通知,可以传NULL

//将 hcallbackWnd 存储在共享内存区 g_hMainWnd 中,用于在事件处理函数中发送消息到主窗口

//setWinEventHook 函数用于设置事件钩子,监听指定范围的窗口事件,在这里监听所有事件,WINEVENT_OUTOFCONTEXT 标志表示事件处理函数在非钩子线程中调用,

//而是位于独立线程中,被系统自行调度使用,无需注入到目标进程中.这是区别于消息hook的地方,消息钩子需要注入到目标进程中,而事件钩子不需要.

//setwineventhook 函数的参数说明:

// eventMin: 监听的最小事件类型,这里设置为 EVENT_MIN,表示监听所有事件

// eventMax: 监听的最大事件类型,这里设置为 EVENT_MAX,表示监听所有事件

// hmodWinEventProc: 事件处理函数所在的模块句柄,这里设置为 NULL,表示使用当前进程的模块

// pfnWinEventProc: 事件处理函数的指针,这里设置为 WinEventProc,表示使用上面定义的事件处理函数

// idProcess: 监听的进程ID,这里设置为 0,表示监听所有进程

// idThread: 监听的线程ID,这里设置为 0,表示监听所有线程

// dwFlags: 监听标志,这里设置为 WINEVENT_OUTOFCONTEXT,表示事件处理函数在非钩子线程中调用

extern "C" __declspec(dllexport)

BOOL APIENTRY StartMonitoring(HWND hCallbackWnd) {

    g_hMainWnd = hCallbackWnd;

    g_hEventHook = SetWinEventHook(

        EVENT_MIN, EVENT_MAX,

        NULL, WinEventProc,

        0, 0,

        WINEVENT_OUTOFCONTEXT);

    return g_hEventHook != NULL;

}

//导出函数,用于停止监控窗口事件

//该函数会取消之前设置的事件钩子,释放资源

//unhookwinevent 函数用于取消事件钩子,释放资源

extern "C" __declspec(dllexport)

BOOL APIENTRY StopMonitoring() {

    return UnhookWinEvent(g_hEventHook);

}

// DLL入口点函数,用于处理DLL的加载和卸载事件

// 当DLL被加载或卸载时,系统会调用这个函数

// 参数说明:

// hModule: DLL模块的句柄

// ul_reason: 卸载原因,可以是 DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH, DLL_THREAD_DETACH, DLL_PROCESS_DETACH

// lpReserved: 保留参数,通常为NULL

// 在这里处理 DLL_PROCESS_DETACH 事件,即当DLL被卸载时,取消事件钩子

//dll卸载过程是在所有线程都结束后,才会调用 DllMain 函数,因此可以安全地取消事件钩子

// 其他事件可以忽略,因为我们只关心 DLL_PROCESS_DETACH 事件

//返回值是固定的 TRUE,表示 DLL 的入口点函数执行成功

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason, LPVOID lpReserved) {

    switch (ul_reason) {

    case DLL_PROCESS_DETACH:

        if (g_hEventHook) UnhookWinEvent(g_hEventHook);

        break;

    }

    return TRUE;

}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容