在我的 动态链接文件dll的使用 和
VC++生成DLL(DynamicLinkLibrary… 两篇博文基础上
测试DLL的入口函数dllMain的作用。
在
VC++生成DLL(DynamicLinkLibrary… 博文实例Dll2.dll的源代码Dll2.cpp 中加入
如下代码:
#include
#include
BOOL WINAPI DllMain (HANDLE hInst,
ULONG ul_reason_for_call,
LPVOID lpReserved )
{
switch( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
//注:句柄就是指向指针的指针
{
HWND hwnd = GetForegroundWindow();
//获得当前活动的窗口句柄hwnd
HDC hdc = GetDC(hwnd);
//获得当前活动窗口的内存句柄
static char buf[20];
sprintf(buf,"进程调用");
TextOut(hdc,0,0,buf,strlen(buf));
//向当前活动的窗口显示“进程调用”字符串
ReleaseDC(hwnd,hdc);
}
break;
case DLL_THREAD_ATTACH:
{
HWND hwnd = GetForegroundWindow();
HDC hdc = GetDC(hwnd);
static char buf[20];
sprintf(buf,"线程调用");
TextOut(hdc,0,0,buf,strlen(buf));
ReleaseDC(hwnd,hdc);
}
break;
case DLL_THREAD_DETACH:
{
HWND hwnd = GetForegroundWindow();
HDC hdc = GetDC(hwnd);
static char buf[20];
sprintf(buf,"进程卸载");
TextOut(hdc,0,0,buf,strlen(buf));
ReleaseDC(hwnd,hdc);
}
break;
case DLL_PROCESS_DETACH:
{
HWND hwnd = GetForegroundWindow();
HDC hdc = GetDC(hwnd);
static char buf[20];
sprintf(buf,"线程卸载");
TextOut(hdc,0,0,buf,strlen(buf));
ReleaseDC(hwnd,hdc);
}
break;
}
return TRUE;
}
编译->链接->Ok 将新生成的 Dll2.dll拷贝到 用
动态链接文件dll的使用
博文中的代码测试编译后生成的可执行程序目录下(在Debug文件下)。直接运行 Dll2Test.exe。效果如下:
3. BOOL WINAPI DllMain( )具体使用方法
DLL应用程序的入口点是DllMain
对程序员来说,DLL应用程序的入口点是DllMain。
DllMain负责初始化(Initialization)和结束(Termination)工作,每当一个新的进程或者该进程的新的线程访问DLL时,或者访问DLL的每一个进程或者线程不再使用DLL或者结束时,都会调用DllMain。
但是,使用TerminateProcess或TerminateThread结束进程或者线程,不会调用DllMain。
DllMain的函数原型符合DllEntryPoint的要求,有如下结构:
BOOL WINAPI DllMain (HANDLE hInst,
ULONG ul_reason_for_call,LPVOID lpReserved)
{
switch( ul_reason_for_call )
{
case DLL_PROCESS_ATTACH:
...
case DLL_THREAD_ATTACH:
...
case DLL_THREAD_DETACH:
...
case DLL_PROCESS_DETACH:
...
}
return TRUE;
}
其中:
参数1包含了DLL的实例句柄,这个值用于标识DLL的文件映像被映射到进程的地址空间中的虚拟内存地址
参数2是指调用DllMain的类别,四种取值:新的进程要访问DLL;新的线程要访问DLL;
一个进程不再使用DLL(Detach from DLL);一个线程不再使用DLL(Detach from DLL)。参数3保留。
如果程序员不指定DllMain,则编译器使用它自己的DllMain,该函数仅仅返回TRUE。
规则DLL应用程序使用了MFC的DllMain,它将调用DLL程序的应用程序对象(从CWinApp派生)
的InitInstance函数和ExitInstance函数。扩展DLL必须实现自己的DllMain。
必须记住:
DLL使用DllMain函数来对他们进行初始化,当你的DllMain函数执行时,同一个地址空间中的其他DL可能尚未执行他们的DllMain函数,这就意味着他们尚未初始化,因此你应该避免调用从其他DLL中输入的函数。