V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Kasumi20
V2EX  ›  C++

VS2019 可以在 DllMain 里面创建线程, VS2017 则会被一直挂起?

  •  
  •   Kasumi20 ·
    develon2015 · 2022-03-11 15:51:01 +08:00 · 1553 次点击
    这是一个创建于 989 天前的主题,其中的信息可能已经有所发展或是发生改变。

    用 2017 工具链编译, 创建线程这一步就卡住不运行了:

    bI0Uts.png

    换 2019 编译,线程运行正常,钩子成功注册:

    bIBiNj.png

    C++代码:

    #include <Windows.h>
    #include <stdio.h>
    #include <thread>
    
    extern "C" {
        __declspec(dllexport) BOOL WINAPI DllMain(
            HINSTANCE hinstDLL, // handle to DLL module
            DWORD fdwReason,    // reason for calling function
            LPVOID lpReserved)  // reserved
        {
            // Perform actions based on the reason for calling.
            switch (fdwReason)
            {
            case DLL_PROCESS_ATTACH:
            {
                // Initialize once for each new process.
                // Return FALSE to fail DLL load.
                printf("附加到进程\n");
                std::thread th([]{
                    HHOOK hook = SetWindowsHookExW(WH_KEYBOARD_LL, (HOOKPROC)[](int code, WPARAM wParam, LPARAM lParam)->LRESULT{
                        KBDLLHOOKSTRUCT *p = (KBDLLHOOKSTRUCT *)lParam;
                        // Do the wParam and lParam parameters contain information about a keyboard message.
                        if (code == HC_ACTION)
                        {
                            // Messsage data is ready for pickup
                            if (wParam == WM_SYSKEYDOWN || wParam == WM_KEYDOWN)
                            {
                                if (p->vkCode == VK_LWIN)
                                {
                                    printf("拦截 KeyDown 事件\n");
                                    return TRUE;
                                }
                            }
                        }
                        // hook procedure must pass the message *Always*
                        return CallNextHookEx(NULL, code, wParam, lParam);
                    }, NULL, 0);
                    printf("hook = %p\n", hook);
                    MSG msg = {0};
                    while (1) {
                        GetMessage(&msg, NULL, 0, 0);
                        TranslateMessage(&msg);
                        DispatchMessage(&msg);
                    }
                });
                th.detach();
                break;
            }
    
            case DLL_THREAD_ATTACH:
                // Do thread-specific initialization.
                printf("附加到线程\n");
                break;
    
            case DLL_THREAD_DETACH:
                // Do thread-specific cleanup.
                printf("从线程分离\n");
                break;
    
            case DLL_PROCESS_DETACH:
                // Perform any necessary cleanup.
                printf("从进程分离\n");
                break;
            }
            return TRUE; // Successful DLL_PROCESS_ATTACH.
        }
    }
    
    5 条回复    2022-03-11 16:48:47 +08:00
    x1596357
        1
    x1596357  
       2022-03-11 15:54:02 +08:00
    Kasumi20
        2
    Kasumi20  
    OP
       2022-03-11 15:58:22 +08:00
    @x1596357 那为什么换 2019 编译又可以运行呢
    codehz
        3
    codehz  
       2022-03-11 16:03:04 +08:00 via Android
    @Kasumi20 没必要研究这种巧合(
    基于巧合写代码的结果就是一个不小心就被破坏了
    ysc3839
        4
    ysc3839  
       2022-03-11 16:44:11 +08:00
    感觉是 X-Y Problem https://coolshell.cn/articles/10804.html
    看上去你是注入 DLL 之后再设置一个 low level keyboard hook ?为什么要这么做?直接在另一个进程中跑不行吗?
    yulon
        5
    yulon  
       2022-03-11 16:48:47 +08:00
    首先 DllMain 里不推荐创建线程,如果真要创建线程请用 CreateThread ,用 std::thread 和 _beginthread 都有可能死锁,因为要初始化语言标准库。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1284 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 17:30 · PVG 01:30 · LAX 09:30 · JFK 12:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.