DLL相关的东西

1、DLL的加载方式

隐式:

#pragma comment(lib, "XX.lib");

编译器去查找名为XX.dll的DLL,除了名字相同,该DLL和该LIB的GUID也相同。

显式:

HINSTANCE   hInst = LoadLibrary(TEXT("XX.dll"));

if(NULL == hInst)  retrun;

HINSTANCE hInst = LoadLibrary(TEXT("XX.dll"), NULL,   FLAGS);

第三个参数为一些标志,详见核心编程。

2、DLL的入口函数

原型

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

其中hModule为该DLL在当前进程地址空间中的位置,ul_reason_for_call为调用此函数的原因,lpReserved如果为显式加载则为0,如果为隐式加载则为非0。

详细说一下ul_reason_for_call

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
#ifdef _DEBUG switch (ul_reason_for_call)
{
//只在该DLL第一次加载进地址空间的时候被调用一次
//此后当该DLL被加载进不同进程的地址空间时让然不调用
//当主调线程通过该reason调用DllMain函数时,主调线程不会收到DLL_THREAD_ATTACH通知
case DLL_PROCESS_ATTACH:
OutputDebugString(TEXT("\r\n***********B Dll DLL_PROCESS_ATTACH ***********\r\n"));
break; //当该DLL已经被加载到进程地址空间后,当有新【线程创建】的时候,新创建的线程先执行此段代码
//然后再去执行线程本身的代码
//不管有几个DLL,每个DLL的此处代码都会被新线程执行
case DLL_THREAD_ATTACH:
OutputDebugString(TEXT("\r\n***********B Dll DLL_THREAD_ATTACH ***********\r\n"));
break; //当该DLL已经被加载到进程地址空间后,当有【线程结束】的时候,该线程结束之前会调用此处代码
//然后才返回
//不管有几个DLL,每个DLL的此处代码都会被执行
case DLL_THREAD_DETACH:
OutputDebugString(TEXT("\r\n***********B Dll DLL_THREAD_DETACH *********** \r\n"));
break; //只有在该DLL从内存中卸载的时候才会被调用一次
case DLL_PROCESS_DETACH:
OutputDebugString(TEXT("\r\n***********B Dll DLL_PROCESS_DETACH ***********\r\n"));
break;
} #endif return TRUE;
}

demo

有两个DLL, ADll.dll 和 BDll.dll

在程序中加载这个两个DLL, 然后创建一个新线程,看输出

//加载DLL
void CUseABDllDlg::OnBnClickedBtnLoadlib()
{
HINSTANCE hInstA = LoadLibrary(_T("ADll.dll"));
HINSTANCE HIntB = LoadLibrary(_T("BDll.dll"));
if (NULL == hInstA || NULL == HIntB)
{
AfxMessageBox(_T("加载DLL失败"));
return;
}
} //线程函数
UINT WINAPI WorkThread(LPVOID lpParam)
{
#ifdef _DEBUG
OutputDebugString(TEXT("\r\n&&&&&&&&&&&&&&&&&&线程被创建&&&&&&&&&&&&&&&&&\r\n"));
#endif return 0U;
} //创建线程
void CUseABDllDlg::OnBnClickedButton2()
{
HANDLE hThread = (HANDLE)_beginthreadex(NULL, , WorkThread, NULL, , NULL);
if (NULL == hThread || INVALID_HANDLE_VALUE == hThread)
{
AfxMessageBox(_T("创建线程失败"));
}
}

输出

结论:

每创建一个新线程,当前进程地址空间中的DLL的DllMain函数都会通过DLL_THREAD_ATTACH通知被调用一次

每结束一个线程,进程地址空间空的DLL的DllMain函数都会通过DLL_THREAD_DETACH通知被调用一次。

【windows核心编程】DLL相关(1)的更多相关文章

  1. windows核心编程 DLL技术 【转】

    注:本文章转载于网络,源地址为:http://blog.csdn.net/ithzhang/article/details/7051558 本篇文章将介绍DLL显式链接的过程和模块基地址重定位及模块绑 ...

  2. 《Windows核心编程系列》二十谈谈DLL高级技术

    本篇文章将介绍DLL显式链接的过程和模块基地址重定位及模块绑定的技术. 第一种将DLL映射到进程地址空间的方式是直接在源代码中引用DLL中所包含的函数或是变量,DLL在程序运行后由加载程序隐式的载入, ...

  3. 《windows核心编程系列》十九谈谈使用远程线程来注入DLL。

    windows内的各个进程有各自的地址空间.它们相互独立互不干扰保证了系统的安全性.但是windows也为调试器或是其他工具设计了一些函数,这些函数可以让一个进程对另一个进程进行操作.虽然他们是为调试 ...

  4. 《windows核心编程系列》十七谈谈dll

    DLL全称dynamic linking library.即动态链接库.广泛应用与windows及其他系统中.因此对dll的深刻了解,对计算机软件开发专业人员来说非常重要. windows中所有API ...

  5. 《Windows核心编程》读书笔记 上

    [C++]<Windows核心编程>读书笔记 这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对 ...

  6. C++Windows核心编程读书笔记

    转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...

  7. 【转】《windows核心编程》读书笔记

    这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...

  8. 《windows核心编程系列》二十一谈谈基址重定位和模块绑定

    每个DLL和可执行文件都有一个首选基地址.它表示该模块被映射到进程地址空间时最佳的内存地址.在构建可执行文件时,默认情况下链接器会将它的首选基地址设为0x400000.对于DLL来说,链接器会将它的首 ...

  9. 《windows核心编程系列》十六谈谈内存映射文件

    内存映射文件允许开发人员预订一块地址空间并为该区域调拨物理存储器,与虚拟内存不同的是,内存映射文件的物理存储器来自磁盘中的文件,而非系统的页交换文件.将文件映射到内存中后,我们就可以在内存中操作他们了 ...

  10. windows核心编程 - 线程同步机制

    线程同步机制 常用的线程同步机制有很多种,主要分为用户模式和内核对象两类:其中 用户模式包括:原子操作.关键代码段 内核对象包括:时间内核对象(Event).等待定时器内核对象(WaitableTim ...

随机推荐

  1. Unix环境编程之定时、信号与中断

    在linux下实现精度较高的定时功能,需要用到setitimer 和 getitimer函数. 函数原型: #include <sys/time.h> int getitimer(int ...

  2. Photoshop:热气球的制作方法

    大致流程: 1.做等宽色块,加内发光 2.变形->膨化,弯曲20% 3.加高光和投影层,增加立体感 4.制作多列,合并后,滤镜->扭曲->球面化100%2次(注意放在在正方形画布中间 ...

  3. WCF入门(九)--WCF实例管理

    这组由Windows通讯基础(WCF)结合一组消息(客户端请求)服务实例所采用的技术被称为实例管理.一个完全由三种类型实例激活支持WCF,它们如下所述. 1.每个调用服务 每次调用服务是Windows ...

  4. Android设置TextView显示一行或多行

    在listView的item中或者是特殊的业务需求中,会要求TextView的内容不完全显示,只有通过一个指定的操作后才显示所有的,比如说一个按钮或者是其它的什么控件. 要想实现这个效果并不难,只要控 ...

  5. checkbox 全选、全不选、反选 插件

    jquery.checkbox.js: ;(function($,window,document,undefined){ $.fn.check=function(mode){ mode= mode | ...

  6. GridView官方教程及示例

    Grid View GridView is a ViewGroup that displays items in a two-dimensional, scrollable grid. The gri ...

  7. Android开发之关于ListView中adapter调用notifyDataSetChanged无效的原因

    1.数据源没有更新,调用notifyDataSetChanged无效. 2.数据源更新了,但是它指向新的引用,调用notifyDataSetChanged无效. 3.数据源更新了,但是adpter没有 ...

  8. TCP/IP 与OSI结构图

    OSI参考模型各层的作用 物理层:在物理媒体上传输原始的数据比特流. 数据链路层:将数据分成一个个数据帧,以数据帧为单位传输.有应有答,遇错重发. 网络层:将数据分成一定长度的分组,将分组穿过通信子网 ...

  9. BCB遍历所有窗体的组件

    for(iFormIdx=0; iFormIdx<Screen->FormCount; iFormIdx++) { TForm *pForm = Screen->Forms[iFor ...

  10. sdut 2934 人活着系列之平方数 (完全背包变形)

    题目链接 分析:完全背包的变形,每一层的d[]数组代表这一层的这个数新加入以后所构成的val的种类. #include <iostream> #include <cstdio> ...