Windows程序中加载并使用动态链接库

1 GetProcAddress()

1.1函数原型

GetProcAddress函数检索指定的动态链接库(DLL)中的输出库函数地址。

函数原型:

FARPROC GetProcAddress(

HMODULE hModule, // DLL模块句柄

LPCSTR lpProcName // 函数名

);

hModule

[in] 包含此函数的DLL模块的句柄。LoadLibrary、
AfxLoadLibrary
 或者GetModuleHandle函数可以返回此句柄。

lpProcName

[in] 包含函数名的以NULL结尾的字符串,或者指定函数的序数值。如果此参数是一个序数值,它必须在一个字的底字节,高字节必须为0。

返回值:

如果
函数调用成功,返回值是DLL中的输出函数地址。

如果
函数调用失败,返回值是NULL。得到进一步的
错误信息,调用函数GetLastError。

1.2 注释

GetProcAddress函数被用来检索在DLL中的输出函数地址。

lpProcName
指针指向的函数名,拼写和大小写必须和DLL
源代码中的
模块定义文件(.DEF)中输出段(EXPORTS)中指定的相同。Win32 API函数的输出名可能不同于你在代码中调用的这些函数名,这个不同被宏隐含在相关的SDK头文件中。如果想得到更多信息,请参考Win32函数原型(Win32 Function Prototypes)。

lpProcName参数能够识别DLL中的函数,通过指定一个与函数相联系的序数值(在.DEF中的EXPORTS段)。GetProcAddress函数验证那个指定的序数值是否在输出的序数1和最高序数值之间(在.DEF中)。函数用这个序数值作为索引从函数表中读函数地址,假如.DEF 文件不连续地定义函数的序数值,如从1到N(N是输出的函数序数值),错误将会发生,GetProcAddress将会返回一个错误的、非空的地址,虽然指定的序数没有对应的函数。

为了防止函数不存在,函数应该通过名字指定而不是序数值。

要求:

Windows NT/2000: 要求
Windows NT 3.1
 或以后版本。

Windows 95/98: 要求Windows 95 或以后版本。

头文件: 在Winbase.h中声明,include Windows.h。

库文件: Use Kernel32.lib。

1.3 参考代码

动态链接库纵览(
Dynamic-Link Libraries
 Overview), 动态链接库函数(Dynamic-Link Library Functions),FreeLibrary, GetModuleHandle, LoadLibrary

示例代码:

调用KERNEL32.DLL中的RegisterServiceProcess(仅在Windows98中适用)

HMODULE hModule=GetModuleHandle("kernel32.dll");

if (hModule)

  {

  typedef DWORD (CALLBACK *LPFNREGISTER)(DWORD,DWORD);

  LPFNREGISTER lpfnRegister;

  lpfnRegister=(LPFNREGISTER)GetProcAddress(hModule,"RegisterServiceProcess");

  if (lpfnRegister)

  {

  (*lpfnRegister)(NULL,1L);

  }

  }

2 LoadLibrary()

HMODULE WINAPI LoadLibrary( _In_ LPCTSTR lpFileName);

Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long

载入指定的
动态链接库,并将它映射到当前进程使用的
地址空间。一旦载入,即可访问库内保存的资源

Long,成功则返回库模块的句柄,零表示失败。会设置GetLastError

参数 类型及说明

lpLibFileName String,指定要载入的
动态链接库的名称。采用与CreateProcess函数的lpCommandLine参数指定的同样的搜索顺序

注解

一旦不需要,用FreeLibrary函数释放DLL

3 FreeLibrary()

Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count. When the reference count reaches zero, the module is unloaded from the address space of the calling process and the handle is no longer valid.

3.1 函数原型

BOOL WINAPI FreeLibrary(
  _In_  HMODULE hModule
);

Parameters

hModule
 [in]

A handle to the loaded library module. The LoadLibraryLoadLibraryExGetModuleHandle, or GetModuleHandleEx function returns this handle.

Return value

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, call the GetLastError function.

3.2 注释

The system maintains a per-process reference count for each loaded module. A module that was loaded at process initialization due to load-time dynamic linking has a reference count of one. The reference count for a module is incremented each time the module is loaded by a call to LoadLibrary. The reference count is also incremented by a call to LoadLibraryEx unless the module is being loaded for the first time and is being loaded as a data or image file.

The reference count is decremented each time the FreeLibrary or FreeLibraryAndExitThread function is called for the module. When a module‘s reference count reaches zero or the process terminates, the system unloads the module from the address space of the process. Before unloading a library module, the system enables the module to detach from the process by calling the module‘s DllMain function, if it has one, with the DLL_PROCESS_DETACH value. Doing so gives the library module an opportunity to clean up resources allocated on behalf of the current process. After the entry-point function returns, the library module is removed from the address space of the current process.

It is not safe to call FreeLibrary from DllMain. For more information, see the Remarks section in DllMain.

Calling FreeLibrary does not affect other processes that are using the same module.

Use caution when calling FreeLibrary with a handle returned by GetModuleHandle. The GetModuleHandle function does not increment a module‘s reference count, so passing this handle to FreeLibrary can cause a module to be unloaded prematurely.

A thread that must unload the DLL in which it is executing and then terminate itself should call FreeLibraryAndExitThread instead of calling FreeLibrary and ExitThread separately. Otherwise, a race condition can occur. For details, see the Remarks section of FreeLibraryAndExitThread.

时间: 2024-10-12 22:51:39

Windows程序中加载并使用动态链接库的相关文章

Windows Phone 8加载外部动态链接库DLL(非安装包内的)

Windows Phone 8加载外部动态链接库DLL(非安装包内的) 在<动态加载与插件化>中大概介绍了下,wp8加载非安装包的下动态链接库,这次详细梳理下. 加载外部DLL主要的原理: 通过NtCurrentTeb获得线程环境块 从线程环境块中获得进程环境块 在进程环境块中加载过得DLL链表 从链表中找到kernelbase.dll的模块句柄 从kernelbase.dll中获得LoadLibraryEx函数地址 加载指定地址下的DLL 相关的结构体: typedef struct _CL

cad中在c#.net中加载lisp程序的方法

主要是想将以前的lisp程序整合到现在的.net菜单中才会这么干的 using Autodesk.AutoCAD.Windows; using Autodesk.AutoCAD.Runtime; using System.Windows.Forms; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.ApplicationServices; usi

磁盘中运行的程序必须加载到内存才能运行的原因

计算机中主要的存储部件是内存和磁盘.磁盘中存储的程序必须加载到内存之后才能运行.在磁盘中保存的原始程序是无法直接运行的.这是因为,负责解析和运行程序内容的CPU,需要通过内部程序计数器来指定内存地址,然后才能读出程序.即使CPU可以直接读出并运行磁盘中保存的程序,由于磁盘读取速度慢,程序的运行速度还是会降低的.总之,存储在磁盘中的程序需要读入到内存后才能运行. 原文地址:http://blog.51cto.com/bantu/2119841

Microsoft Corporation 去掉 windows 修改 启动加载 版权

windows 修改 开机界面 boot启动界面 windows 修改 启动加载 版权 windows 系统如何修改开机画面的版权文字"Microsoft Corporation ... ◎Microsoft Corporation Microsoft Corporation 去掉 作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱:[email protected] E-mail: 313134555 @qq.com 通过16进制的编辑器(我用的是winhex)打开winlo

【摘】如何从程序集中加载及卸载插件

目前要做一个windows Service,内部任务分别使用应用程序域进行隔离.针对应用程序域中加载dll,并调用dll的方法启动任务遇到了一些麻烦,下文中的事例完整的解决了问题. ------------------------------------- 在软件开发的领域中,插件技术一直是一项非常实用的技术.许多优秀的软件产品都提供了通过加载插件来扩展.丰富产品本身功能的能力.而像Firefox.Eclipse之类的软件,更是将插件的功能发挥到了极致.顺便做点广告的是,我们的Mussel框架便

ArcGIS API for Silverlight中加载Google地形图(瓦片图)

原文:ArcGIS API for Silverlight中加载Google地形图(瓦片图) 在做水利.气象.土地等行业中,若能使用到Google的地形图那是再合适不过了,下面就介绍如何在ArcGIS API for Silverlight中加载Google地 形图.先上一个图,初步制作,待后续继续改进 ArcGIS API for Silverlight 中的ArcGISTiledMapServiceLayer图层,继承自TiledMapServiceLayer.如果想实现自己的缓存地图图 层

程序的加载和执行(六)——《x86汇编语言:从实模式到保护模式》读书笔记26

程序的加载和执行(六)--<x86汇编语言:从实模式到保护模式>读书笔记26 通过本文能学到什么? NASM的条件汇编 用NASM编译的时候,通过命令行选项定义宏 Makefile的条件语句 在make命令行中覆盖Makefile中的变量值 第13章习题解答 复习如何构造栈段描述符 我们接着上篇博文说. 在我修改后的文件中,用到了条件汇编. 比如: %ifdef DEBUG put_core_salt: ;打印内核的符号 ... ... put_usr_salt: ;打印用户的符号 ... .

程序的加载和执行(三)——《x86汇编语言:从实模式到保护模式》读书笔记23

程序的加载和执行(三)--读书笔记23 接着上次的内容说. 关于过程load_relocate_program的讲解还没有完,还差创建栈段描述符和重定位符号表. 分配栈空间与创建栈段描述符 462 ;建立程序堆栈段描述符 463 mov ecx,[edi+0x0c] ;4KB的倍率 464 mov ebx,0x000fffff 465 sub ebx,ecx ;得到段界限 466 mov eax,4096 467 mul dword [edi+0x0c] 468 mov ecx,eax ;准备为

IOS 应用程序启动加载过程(从点击图标到界面显示)

今天帮同事解决问题的时候发现,造成程序BUG的原因是同事对程序的启动和试图的加载过程不熟悉.所以当局部代码没有问题,但是程序一运行却总不是我们想要结果的时候,我们应该想想是不是因为我们忽略了试图加载过程的原因.下面我们用一个例子来简单介绍一下启动过程中常见的几个方法.首先我们通过XIB 创建了一个试图控制器(名字叫Empty ,不要问我为为啥它叫这个名字,因为我太懒了,鼠标点快了就没去该),又创建了一个UIView的子类(MyView),并且将Empty的对象 设置为窗口的跟控制器,MyView