DLLMain 简单介绍

C++-dllmain介绍 dllmain 百度解释的很清楚 跟exe有个main或者WinMain入口函数一样,DLL也有一个入口函数,就是DllMain,对于动态链接库,DllMain是一个可选的入口函数 入口函数定义 BOOL WINAPI DllMain( _In_ HINSTANCE hinstDLL, // 指向自身的句柄 _In_ DWORD fdwReason, // 调用原因 _In_ LPVOID lpvReserved // 隐式加载和显式加载 ); 系统在调用LoadLibrary和Fre 阅读详情

From: http://www.cppblog.com/Hero/archive/2009/12/04/102537.aspx

1 DLL的进入/退出函数

1.1 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函数的。

1.2 何时调用DllMain

系统是在什么时候调用DllMain函数的呢?静态链接时,或动态链接时调用LoadLibrary和FreeLibrary都会调用DllMain函数。DllMain的第三个参数fdwReason指明了系统调用Dll的原因,它可能是:  DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH, DLL_THREAD_ATTACH, DLL_THREAD_DETACH. 以下从这四种情况来分析系统何时调用了DllMain。

 

1.2.1 DLL_PROCESS_ATTACH

大家都知道,一个程序要调用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函数。

1.2.2 DLL_PROCESS_DETACH

当DLL被从进程的地址空间解除映射时,系统调用了它的DllMain,传递的fdwReason值是DLL_PROCESS_DETACH。当DLL处理该值时,它应该执行进程相关的清理工作。那么什么时候DLL被从进程的地址空间解除映射呢?两种情况:

 

◆FreeLibrary解除DLL映射(有几个LoadLibrary,就要有几个FreeLibrary )
◆进程结束而解除DLL映射,在进程结束前还没有解除DLL的映射,进程结束后会解除DLL映射。(如果进程的终结是因为调用了 TerminateProcess,系统就不会用DLL_PROCESS_DETACH来调用DLL的DllMain函数。这就意味着DLL在进程结束前没有机会执行任何清理工作。)

注意:当用 DLL_PROCESS_ATTACH调用DLL的DllMain函数时,如果返回FALSE,说明没有初始化成功,系统仍会用 DLL_PROCESS_DETACH调用DLL的DllMain函数。因此,必须确保清理那些没有成功初始化的东西。

 

可参考DllMainTest的DLL_PROCESS_DETACH_Test函数。

1.2.3 DLL_THREAD_ATTACH

当进程创建一线程时,系统查看当前映射到进程地址空间中的所有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函数,哪怕是线程中建立线程也一样。

1.2.4 DLL_THREAD_DETACH

如果线程调用了ExitThread来结束线程(线程函数返回时,系统也会自动调用ExitThread),系统查看当前映射到进程空间中的所有DLL文件映像,并用DLL_THREAD_DETACH来调用DllMain函数,通知所有的DLL去执行线程级的清理工作。

注意:如果线程的结束是因为系统中的一个线程调用了TerminateThread,系统就不会用值DLL_THREAD_DETACH来调用所有DLL 的DllMain函数。

1.3 为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帮助文档查看,搜索时,打钩“仅搜索标题”会更快定位。

 

DllMain详解 - 生活 - 无敌

 

按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”(图中蓝色高亮的地方),要注意位置,我试了,要把/D放到/GZ后面也会链接错误,我也不懂为什么,^_^。按 OK,再次编译,成功。大家可以自己测试下到底有没有更改成功,什么,如果测试?打出调式信息啊。

DllMain详解 - 生活 - 无敌

 

1.4 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.

 

windows:加载dll时的DLLMain介绍 在实际开发中,通常情况下,系统自带的初始化和清理机制(如全局变量初始化和析构、自动内存管理等)已经足够。然而,有些特定场景下,需要开发者自己在DllMain中处理和。以下是一些可能的情况:线程本地存储(TLS)当需要在每个线程中维护独立的数据(如线程本地存储),必须手动进行线程初始化和清理。例如,多线程日志记录、线程特定的配置等。示例:每个线程都有独立的日志文件句柄或配置对象。资源管理当需要在DLL加载时分配全局资源(如文件句柄、网络连接)并在卸载时释放这些资源时,必须手动进行初始化和清理。示例。 阅读详情

相关推荐

VC++动态链接库(DLL)编程深入浅出,DLL编写教程 两篇

最简单的dll并不比c的helloworld难,只要一个DllMain函数即可,包含objbase.h头文件(支持COM技术的一个头文件)。若你觉得这个头文件名字难记,那么用windows.H也可以。源代码如下:dll_nolib.cpp #include #include BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) { HANDLE g_hModule; switch(dwReason) { case DLL_PROCESS_ATTACH: cout<<"Dll is attached!"<<endl; g_hModule = (HINSTANCE)hModule; break; case DLL_PROCESS_DETACH: cout<<"Dll is detached!"<<endl; g_hModule=NULL; break; } return true; } 其中DllMain是每个dll的入口函数,如同c的main函数一样。DllMain带有三个参数,hModule表示本dll的实例句柄(听不懂就不理它,写过windows程序的自然懂),dwReason表示dll当前所处的状态,例如DLL_PROCESS_ATTACH表示dll刚刚被加载到一个进程中,DLL_PROCESS_DETACH表示dll刚刚从一个进程中卸载。当然还有表示加载到线程中和从线程中卸载的状态,这里省略。最后一个参数是一个保留参数(目前和dll的一些状态相关,但是很少使用)。 从上面的程序可以看出,当dll被加载到一个进程中时,dll打印"Dll is attached!"语句;当dll从进程中卸载时,打印"Dll is detached!"语句。 编译dll需要以下两条命令: cl /c dll_nolib.cpp 这条命令会将cpp编译为obj文件,若不使用/c参数则cl还会试图继续将obj链接为exe,但是这里是一个dll,没有main函数,因此会报错。不要紧,继续使用链接命令。 Link /dll dll_nolib.obj 这条命令会生成dll_nolib.dll。 注意,因为编译命令比较简单,所以本文不讨论nmake,有兴趣的可以使用nmake,或者写个bat批处理来编译链接dll。 加载DLL(显式调用)

【C#学习笔记】C#调用C++ dll ————(2021/2/17学习笔记)

1

qq_37704442的博客 491

加权余量法求解偏微分方程

加权余量法(Weighted Residual Method)是一种数值方法,用于求解偏微分方程(PDEs)。其基本思想是将偏微分方程的残差(或余量)通过加权函数加权,并使加权余量在定义域上为零,从而形成一组代数方程进行求解。

leizhengshenglzs的博客 1791

DLL中的dllMain入口函数的使用

在我的 动态链接文件dll的使用  和VC++生成DLL(DynamicLinkLibrary… 两篇博文基础上 测试DLL的入口函数dllMain的作用。 在VC++生成DLL(DynamicLinkLibrary… 博文实例Dll2.dll的源代码Dll2.cpp 中加入 如下代码: #include #include BOOL WINAPI DllMain (HANDLE hInst,

梦想博客 1671

软件工程:数据字典

数据字典

永远怀着至诚之心拥抱世界 4273

【量化入门】Tushare库获取公募基金的历史净值

在本文中,我们将介绍如何使用Python的Tushare库获取公募基金的历史净值。

木头大左的博客 1140

DLL文件_DLLMain函数详解

目录**CODE**1.DLLMain函数类型-APIENTRY CODE //核心的入口函数,动态链接库入口函数 BOOL APIENTRY DllMain( HMODULE hModule, //APIENTRY可以换成WINAPI或者_stdcall 是一种调用约定 DWORD ul_reason_for_call, LPVOID lpReserved )

weixin_46967682的博客 7367

QMK键盘固件开发零基础教程(2025全新重制版)

《QMK键盘固件开发零基础教程(2025全新重制版)》是一套专为键盘爱好者和开发者设计的全面教程,旨在帮助用户从零基础快速掌握最新的QMK固件开发技术。教程基于2025年最新的QMK版本(0.19.8+),解决了旧版教程中的诸多问题,如概念不清、步骤缺失和代码过时等。新版教程提供了详细的图解、完整的项目源码以及从环境配置到高级功能开发的全流程指导。此外,教程还涵盖了2024年QMK生态的重大变革,包括键码系统的重构、编译工具链的更新以及Config文件格式的改变等。付费版教程额外提供独家内容,如新特性解析、

Despacito0o的博客 1121

Reflection反射【C#】

【代码】反射Reflection。

cfqq1989的博客 2448

VIVADO IP核之FIR插值器多相滤波仿真

网络上有许多文章介绍FIR低通滤波器的使用,包括仿真。关于FIR低通滤波器的使用,我之前的文章已经介绍过了,本文将继续深入介绍FIR插值器多相滤波的使用方法,并将FIR插值多相滤波的结果与MATLAB仿真计算的结果比较,验证了FIR插值器多相滤波使用正确。

m0_66360845的博客 3382

SAP HANA CDS View Syntax Options 全解:从语法到工程实践

本文面向SAP HANA工程师,深入解析CDS视图的语法与应用场景。文章涵盖XS Advanced环境下的CDS视图设计要点,包括SELECT基础语法、聚合函数与分组约束、参数化视图实现以及常见连接操作。特别强调工程实践中的注意事项:GROUP BY禁用表达式、原生表名大小写规范、结果集裁剪方式选择等。通过两个真实案例(办公室占用率统计和客户画像分析)展示CDS视图在实际业务中的应用,并提供性能优化建议。全文采用中英文混排规范,技术术语使用反引号标注,旨在为开发者提供清晰的CDS视图开发指南。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 209

为什么不执行 DllMain,C#注入DLL成功

找到DLL注入的例程http://blog.sina.com.cn/s/blog_4d5428240100reac.html 百度到的所有例程几乎跟以下代码一模一样。但经使用发现,虽然提示成功,但并没有执行DLL入口函数DllMain,这个广泛流传的代码,没人验证过吗?问题在哪里呢?? 另外,我使用MHScn.exe注入工具,注入同一个DLL,同一个进程,就能够正常执行DllMai...

netyou的专栏 2316

(七)独立按键

(七)独立按键

m0_52555663的博客 1713

Win32导出变量、类及DllMain函数的介绍

当一个DLL文件(通过隐式链接或显式链接的LoadLibrary)被映射到进程的地址空间时,系统调用该DLL的DllMain函数,并把DLL_PROCESS_ATTACH传递给参数ul_reason_for_call。当使用FreeLibrary时,若该进程的线程的使用计数为0时,操作系统才会使用DLL_PROCESS_DETACH来调用DllMain,如果计数大于0,则只减少该DLL的计数。只有当所有DLL都完成了DLL_THREAD_ATTACH的处理后,新线程才会执行它的线程函数。

【微软MVP】zhaotianff的专栏 1113

基于Simulink的雷达跟踪系统仿真(附源码)

此示例包含对雷达系统的基本特征进行建模的子系统。该模型是用于目标位置和速度检测的雷达系统的典型模型。该示例包括雷达脉冲发生器、射频发射器子系统、移动目标的 Simulink 表示、射频接收器和接收模块(Rx 模块)。

珞瑜的博客 3513

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

DllMain介绍

转自:http://baike.baidu.com/view/3549543.htm   1 DLL的进入/退出函数   1.1 DllMain简介   跟exe有个main或者WinMain入口函数一样,DLL也有一个入口函数,就是DllMain。以“DllMain”为关键字,来看看MSDN帮助文档怎么介绍这个函数的。   The DllMain function is an ...

yangke_love的专栏 169

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

WinAPI【Win32 系统入口函数介绍】WinMain DllMain

WinMain函数 WinMain函数的原型声明如下: int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nCmdShow ); 参数: WinMain函数接收4个参数,这些参数都是在系统调用WinMain函数时,传递给应用程序的。 hInsta

prownd的专栏 2132

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

DllMain中不当操作导致死锁问题的分析--死锁介绍

最近在网上看到一些关于在DllMain中不当操作导致死锁的问题,也没找到比较确切的解答,这极大吸引了我研究这个问题的兴趣。我花了一点时间研究了下,正好也趁机研究了下进程对DllMain的调用规律。因为整个研究篇幅比较长,我觉得还是分开写比较能突出重点。本文先说说死锁。(转载请指明出于breaksoftware的csdn博客)         介绍死锁之前,我说一个我小时候听过的一个故事:

ProgrammingRing的专栏 966

WinAPI【Win32 系统入口函数介绍】WinMain DllMain

WinMain函数 WinMain函数的原型声明如下: int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,int nCmdShow ); 参数: WinMain函数接收4个参数,这些参数都是在系统调用WinMain函数时,传递给应用程序的。 hInstance: ...

weixin_30555753的博客 508

DllMain详解

1  DLL的进入/退出函数 1.1  DllMain简介 跟exe有个main或者WinMain入口函数一样,DLL也有一个入口函数,就是DllMain。以“DllMain”为关键字,来看看MSDN帮助文档怎么介绍这个函数的。 The DllMain function is an optional method of entry into a dynamic-link library (DLL)

Kroosafe的专栏 1万+

4-DllMain详解

当线程C执行DIlMain函数中的代码时,线程B创建线程D,此时系统必须再次用DLL_THREAD_ATTACH来调用SomeDLL.dll的DllMain函数,但这次是让线程D来执行其中的代码。DllMain函数执行的时候,Windows会为它创建一个加载器锁,加载器锁可以被任意需要访问加载到进程中的DLL列表的函数获取到,这其中包括GetModuleHandle和GetModuleFileName之类的函数。DLL的入口函数一般被用作根据不同的通知信号,来执行相关的进程或线程的初始化和清理工作,

weixin_40332490的博客 1230

[转载]DllMain中不当操作导致死锁问题的分析--死锁介绍

(转载于breaksoftware的csdn博客) 最近在网上看到一些关于在DllMain中不当操作导致死锁的问题,也没找到比较确切的解答,这极大吸引了我研究这个问题的兴趣。我花了一点时间研究了下,正好也趁机研究了下进程对DllMain的调用规律。因为整个研究篇幅比较长,我觉得还是分开写比较能突出重点。本文先说说死锁。 介绍死锁之前,我说一个我小时候听过的一个故事: ...

angbagangzhe065140的博客 118

对DllMain的误解

     一直以来对DllMain的了解也就局限于,实验性的在DllMain里面写上: cout        我在DllMain里面这样写的代码:BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){

tangaowen的专栏 4368

MFC DLL中添加DllMain的方法

使用的是MFC DLL,但是却想添加DllMain作为入口函数,但是很明显直接编译肯定编不过.因为在MFC框架中DllMain已经被封装了.所以在这里介绍一个通过编译的简单方法: 右键 -] 项目属性 -] 配置属性 -] c++ -] 预处理器 删除_USRDLL即可

晓阳 的专栏 1342

DllMain

转自:https://docs.microsoft.com/zh-cn/windows/win32/dlls/dllmain

yjianlu的专栏 189
上一篇: Linux内核: 修改TCP/IP调优参数
下一篇: 图象颜色格式相关文章汇总
CodeJoker
博客等级 码龄18年 50粉丝 37原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值