VB DllMain DLL的进入、退出函数详解,VB DllMain DLL的进入、退出函数,VB DllMain DLL的进入、退出详解,VB DllMain DLL的进入函数详解,VB DllMain DLL的退出函数详解,VB DllMain DLL进入函数详解,VB DllMain DLL退出函数详解,VB DllMain DLL进入函数,VB DllMain DLL退出函数,VB DllMain DLL函数详解,VB DllMain DLL函数,VB DllMain函数,VB DllMain DLL,Dll入口点函数,VB DllMain,DllMain 简介,WinMain 入口函数,DLL入口函数,DllMain 入口函数,Const DLL_PROCESS_ATTACH As Long = 1 '当DLL被映射到进程的地址空间时,Const DLL_PROCESS_DETACH As Long = 0 '当DLL被从进程的地址空间解除映射时,Const DLL_THREAD_ATTACH As Long = 2 '当进程创建一线程时,Const DLL_THREAD_DETACH As Long = 3 '当线程调用了 ExitThread 结束线程时,DLL_PROCESS_ATTACH,DLL_PROCESS_DETACH,DLL_THREAD_ATTACH,DLL_THREAD_DETACH,系统调用 DllMain 函数的四种情况,DllMain(ByVal hinstDLL As Long, ByVal fdwReason As Long, ByVal lpvReserved As Long) As Long。
VB DllMain DLL的进入、退出函数详解: DllMain 简介: 跟 exe 有个 main 或者 WinMain 入口函数一样,DLL 也有一个入口函数,就是 DllMain。以“DllMain”为关键字,来看看MSDN帮助文档怎么介绍这个函数的。 The DllMain function is an optional method of entry into a dynamic-link library (DLL)。 简要翻译:对于动态链接库,DllMain是一个可选的入口函数。 这句话很重要,很多初学者可能都认为一个动态链接库肯定要有 DllMain 函数。其实不然,像很多仅仅包含资源信息的 DLL 是没有 DllMain 函数的。 当一个进程载入或卸载一个DLL时,DLLMAIN会被调用(DLLMAIN获得DLL_PROCESS_ATTACH消息),线程也是一样(获得DLL_THREAD_ATTACH消息)。 在静态链接时,或动态链接时调用 LoadLibrary 和 FreeLibrary 都会调用 DllMain 函数。DllMain 的第三个参数 fdwReason 指明了系统调用 dll 的原因,它可能是: Const DLL_PROCESS_ATTACH As Long = 1 '当DLL被映射到进程的地址空间时 以下从这四种情况来分析系统何时调用了DllMain。 当一个程序要调用 Dll 里的函数,首先要先把 DLL 文件映射到进程的地址空间。要把一个 DLL 文件映射到进程的地址空间,有两种方法:静态链接和动态链接的 LoadLibrary 或者 LoadLibraryEx。 当一个 DLL 文件被映射到进程的地址空间时,系统调用该 DLL 的 DllMain 函数,传递的 fdwReason 参数为 DLL_PROCESS_ATTACH。这种调用只会发生在第一次映射时。如果同一个进程后来为已经映射进来的 DLL 再次调用 LoadLibrary 或者 LoadLibraryEx,操作系统只会增加 DLL 的使用次数,它不会再用 DLL_PROCESS_ATTACH 调用 DLL 的 DllMain 函数。不同进程用 LoadLibrary 同一个 DLL 时,每个进程的第一次映射都会用 DLL_PROCESS_ATTACH 调用 DLL 的 DllMain 函数。 可参考 DllMainTest 的 DLL_PROCESS_ATTACH_Test 函数。 当 DLL 被从进程的地址空间解除映射时,系统调用了它的 DLLMain,传递的fdwReason值是 DLL_PROCESS_DETACH。当 DLL 处理该值时,它应该执行进程相关的清理工作。 那么什么时候 DLL 被从进程的地址空间解除映射呢?两种情况: ◆FreeLibrary 解除 DLL 映射(有几个 LoadLibrary,就要有几个 FreeLibrary) 注意:当用 DLL_PROCESS_ATTACH 调用 DLL 的 DllMain 函数时,如果返回 FALSE,说明没有初始化成功,系统仍会用 DLL_PROCESS_DETACH 调用 DLL 的 DllMain 函数。因此,必须确保清理那些没有成功初始化的东西。 可参考 DllMainTest 的 DLL_PROCESS_DETACH_Test 函数。 当进程创建一线程时,系统查看当前映射到进程地址空间中的所有 DLL 文件映像,并用值 DLL_THREAD_ATTACH 调用 DLL 的 DllMain 函数。 新创建的线程负责执行这次的 DLL 的 DllMain 函数,只有当所有的 DLL 都处理完这一通知后,系统才允许进程开始执行它的线程函数。 注意跟 DLL_PROCESS_ATTACH 的区别,我们在前面说过,第 n(n>=2) 次以后把 DLL 映像文件映射到进程的地址空间时,是不再用 DLL_PROCESS_ATTACH 调用 DllMain 的。而 DLL_THREAD_ATTACH 不同,进程中的每次建立线程,都会用值 DLL_THREAD_ATTACH 调用 DllMain 函数,哪怕是线程中建立线程也一样。 如果线程调用了 ExitThread 来结束线程(线程函数返回时,系统也会自动调用 ExitThread),系统查看当前映射到进程空间中的所有 DLL 文件映像,并用 DLL_THREAD_DETACH 来调用 DllMain 函数,通知所有的 DLL 去执行线程级的清理工作。 注意:如果线程的结束是因为系统中的一个线程调用了 TerminateThread,系统就不会用值 DLL_THREAD_DETACH 来调用所有 DLL 的 DllMain 函数。 在早期的 SDK 版本中,DllMain 是叫做 DllEntryPoint。其实有一件鲜为人知的事:一个 Dll 的入口函数名是可以自己定义的。下面我将以 VC++6.0 为例来演示如何更改。首先要说明一点,虽然 DllMain 可以换成其他函数名,但函数的参数和返回值必须和 DllMain 一样。而且这个函数要为 __stdcall 类型(DllMain 本身也是 __stdcall 类型)。 打开 VC++ 菜单 Project\Settings\Link tab\ Output in the Category box,在 Entry-point symbol 中输入要替换 DllMain 的函数名(当然这个函数名是你程序中已经实现的函数)。Entry-point symbol 是干么的呢?可以以关键字“Entry-point symbol”搜索 MSDN 帮助文档查看,搜索时,打钩“仅搜索标题”会更快定位。 按OK后,如果马上编译的话会出现如下错误: LIBCMTD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main Debug/Dll.dll : fatal error LNK1120: 1 unresolved externals 打开 VC++ 菜单 Project\Settings\C/C++ 选项卡,在 Project Options:末尾的地方添加“/D”,要注意位置(/GZ 之前),我试了,要把 /D 放到 /GZ 后面也会链接错误,我也不懂为什么。按OK,再次编译,成功。大家可以自己测试下到底有没有更改成功,什么,如果测试?打出调式信息啊。 DisableThreadLibraryCalls,看帮助就知道它是干么用的:The DisableThreadLibraryCalls function disables the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications for the dynamic-link library (DLL) specified by hLibModule. This can reduce the size of the working code set for some applications. 翻译:DisableThreadLibraryCalls 函数禁止动态链接库(DLL)中 hLibModule 的 DLL_THREAD_ATTACH 和 DLL_THREAD_DETACH 通知消息,这样可以减少一些应用程序工作代码的大小。 VB DllMain 函数示例: Const DLL_PROCESS_ATTACH As Long = 1 '当DLL被映射到进程的地址空间时 Public Function DllMain(ByVal hinstDLL As Long, ByVal fdwReason As Long, ByVal lpvReserved As Long) As Long 'Dll入口点函数 |