使用 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】:我在同一个程序中看到 WinMain
和 cout
。
请说明您创建的项目类型。
您可以在此处查看挂钩示例 - 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的主要内容,如果未能解决你的问题,请参考以下文章
使用 loadLibrary() 在 java 中调用 c++ dll
使用 P/Invoke 调用 dll 时,为啥 LoadLibrary 在某些机器上会失败?
UICollectionView:使用其他手势后未调用 didSelectItemAtIndexPath