使用 LoadLibrary 后未调用 DllMain

Posted

技术标签:

【中文标题】使用 LoadLibrary 后未调用 DllMain【英文标题】:DllMain not called after using LoadLibrary 【发布时间】:2013-01-11 06:33:28 【问题描述】:

我是一名 C++ 初学者(3-4 个月),我正在尝试对 Windows 挂钩进行精益求精。我有一个我试图注入的 DLL 的错误,过了一会儿我意识到我的 DllMain 没有被调用!我几乎查看了 *** 上的每个线程,但无法找出我的问题。我通过将变量初始化为 5,在 DllMain 中将其更改为 1 并在函数中输出变量来发现这一点。变量永远不会改变。这是代码:

int i = 5;

BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved  )

    i=1;
    switch (ul_reason_for_call)
    
    case DLL_PROCESS_ATTACH:
        hDll  = (HINSTANCE) hModule;

        break;

    case DLL_THREAD_ATTACH:  break;
    case DLL_THREAD_DETACH:  break;
    case DLL_PROCESS_DETACH:  break;

    

    return TRUE;


bool InstallHook()
    cout << "INSTALLING HOOK... " << endl;
    cout << i << endl;
    hHook = SetWindowsHookEx(WH_CBT, (HOOKPROC) CBTProc, hDll, 0);
    return hHook != NULL;

这是我正在加载的 DLL...

typedef bool (*InstallHook)();
typedef void (*UninstallHook)();
InstallHook ih;
UninstallHook uh;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)

    switch(msg)
    
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            uh();
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    
    return 0;


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)

    // Bunch of code to initialize a simple window until this: 
    HINSTANCE hDll = LoadLibrary("e:\\projects\\DLL\\ToInject.dll");
    ih = (InstallHook)GetProcAddress(hDll, "InstallHook");
    uh = (UninstallHook)GetProcAddress(hDll, "UninstallHook");
    if (!ih())
        cout << "SUCCESS" << endl;
    else
        cout << "FAILED" << endl;
    
    // other stuff to create a window
    return Msg.wParam;

输出:

INSTALLING HOOK... 
5 // We can see here that the DLL never changed the value of i to 1.
SUCCESS
UNINSTALL HOOK...

【问题讨论】:

记录 DLL 项目的链接器命令行。 仅供参考,DllMain 的第一个参数应该是 HINSTANCE,而不是 HANDLE,但因为它们都是 typedef void *,所以我认为这不会导致您的问题。是否正在导出 DllMain? 【参考方案1】:

按照以下步骤制作一个工作示例(这是用于 Visual Studio):

创建一个新的控制台应用程序; 检查 Dll; 把它放在 dllmain.cpp 中:

dllmain.cpp

// dllmain.cpp : Defines the entry point for the DLL application.

#include "stdafx.h"
#include <string>

std::string test = "not Loaded"; 

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )

    test = "loaded"; //You also change on this location the value of a variable
    switch (ul_reason_for_call)
    
    case DLL_PROCESS_ATTACH:
        MessageBoxA(NULL,"test","test",NULL);
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    
    return TRUE;


extern "C" __declspec (dllexport) bool example()

    MessageBoxA(NULL,test.c_str(),"test",NULL);
    return true;

编译代码,确保它处于发布模式; 创建一个新的控制台应用程序; 检查空项目; 创建一个名为 main.cpp 的新文件; 将此复制到文件中:

Main.cpp

#include <windows.h>

typedef bool (*testFunction)();

testFunction dllFunction;

int main()


    HINSTANCE hDll = LoadLibraryA("example.dll");
    if(hDll)
    
        dllFunction = (testFunction)GetProcAddress(hDll, "example");
        dllFunction();
    

    return 0;

构建项目,确保它处于发布模式; 从控制台应用程序复制您在发布文件夹中创建的 DLL; 运行程序。

它在这里工作。我得到一个带有测试和 1 次加载的 MessageBox。您可以将此代码与您的代码进行比较。希望你能找到问题。

【讨论】:

感谢您的回答。但不幸的是,这并不能解决我的问题。正如我们在我的第一篇文章中看到的那样,我可以毫无问题地访问我的函数 InstallHook 和 UninstallHook。问题是我无法访问 DllMain。来自 msdn “如果指定的模块是尚未为调用进程加载的 DLL,则系统使用 DLL_PROCESS_ATTACH 值调用 DLL 的 DllMain 函数。”这对我不起作用:'(链接:link 奇怪,我的 DLL main 被调用了。我更新了答案,以便您可以看到我的 DllMain。【参考方案2】:

我在同一个程序中看到 WinMaincout。 请说明您创建的项目类型。

您可以在此处查看挂钩示例 - http://www.codeproject.com/Articles/5002/Mousey-Roll-Over-and-Park

【讨论】:

桑蒂!!!这是一个很好的旧代码,每当我对钩子有疑问时,我仍然会参考它:) 谢谢,我去看看这个项目。我有 WinMain 的原因是因为我在打开窗口时尝试测试我的钩子,因为我读到另一个 *** 问题,有时你可能很难从控制台应用程序调试 DllMain。但在那之前,一切都在我的主要功能中,但结果是一样的。【参考方案3】:
extern "C" BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved  )

如果你用C++编译,你必须在DllMain函数的前面加上“extern”C“”

【讨论】:

以上是关于使用 LoadLibrary 后未调用 DllMain的主要内容,如果未能解决你的问题,请参考以下文章

从DllMain调用LoadLibrary

使用 loadLibrary() 在 java 中调用 c++ dll

使用 P/Invoke 调用 dll 时,为啥 LoadLibrary 在某些机器上会失败?

UICollectionView:使用其他手势后未调用 didSelectItemAtIndexPath

成功执行 isCustomResponse() 后未调用 handleChallenge()

system.loadlibrary 路径 能带参数吗