Windows DLL基本原理及为何需要注册

Windows DLL基本原理及为何需要注册

包括刚才提到过的通用文件对话框在内,DLL文件提供了应用程序间共享资源的可能。资源可以是程序对话框、字符串、图标,或者声音文件等。

⑤ 解决应用程序本地化问题

在下载了某个程序的汉化包后,打开汉化说明,经常可以看到用下载包中的DLL文件覆盖掉程序原来的DLL,汉化就完成了。这些程序都是将执行代码和应用程序界面分开编写了,所以汉化者只需简单地将其中和程序界面相关的DLL汉化并发布即可。

3 隐式链接和显式链接

应用程序导入函数与DLL文件中的导出函数进行链接有两种方式:隐式链接和显式链接。

隐式链接(load-time dynamic linking)是指在应用程序中不需指明DLL文件的实际存储路径,程序员不需关心DLL文件的实际装载(由编译器自动完成地址分配)。采用隐式链接方式,程序员在建立一个DLL文件时,链接程序会自动生成一个与之对应的LIB导入文件。该文件包含了每一个DLL导出函数的符号名和可选的标识号,但是并不含有实际的代码。LIB文件作为DLL的替代文件被编译到应用程序项目中。当程序员通过静态链接方式编译生成应用程序时,应用程序中的调用函数与LIB文件中导出符号相匹配,这些符号或标识号进入到生成的EXE文件中。LIB文件中也包含了对应的DLL文件名(但不是完全的路径名),链接程序将其存储在EXE文件内部。当应用程序运行过程中需要加载DLL文件时,Windows根据这些信息发现并加载DLL,然后通过符号名或标识号实现对DLL函数的动态链接。我们使用的大部分系统Dll就是通过这样的方式链接的。若找不到需要的Dll则会给出一个Dll缺少的错误消息。

显式链接(run-time dynamic linking)与此相反。用户程序在编译的时候并没有指明需要哪些Dll,而是在运行起来之后调用Win32 的LoadLibary()函数,去装载Dll。若没有找到Dll则这个函数就会返回一个错误。在用LoadLibary()函数装载Dll之后,应用程序还需要用GetProcAdress()函数去获得Dll输出函数的地址。显式链接方式对于集成化的开发语言比较适合。有了显式链接,程序员就不必再使用导入文件,而是直接调用Win32 的LoadLibary()函数,并指定DLL的路径作为参数。还要说明一点的就是Known Dlls就是保证在通过LoadLibary()去装载系统Dll的时候,只从特定的系统目录去装载,防止装载错。装载的时候会去看注册表下是否有一样的注册表键名。

应用程序怎样找到DLL文件

如果应用程序使用LoadLibrary显式链接,那么在这个函数的参数中可以指定DLL文件的完整路径。如果不指定路径,或是进行隐式链接,Windows将遵循下面的搜索顺序来定位DLL:

I 包含EXE文件的目录,

II 进程的当前工作目录,

III Windows系统目录,

IV Windows目录,

V 列在Path环境变量中的一系列目录。

在Windows上有个注册表键值决定了Dll的搜索顺序:HKLMSystemCurrentControlSetSessionManagerSafeDllSearchMode。在windows 7,server2003,xp sp2中这个值为1,在xp,2000 sp4中为0。

1值时的搜素顺序为:1.可执行文件所在目录,2.系统目录windowssystem32,3. 16位系统目录,4.windows目录,5.当前进程目录。6.环境变量PATH中的目录。

0值时的搜素顺序为:1.可执行文件所在目录,2. 当前进程目录。3.系统目录windowssystem32,4. 16位系统目录,5.windows目录,6.环境变量PATH中的目录。

4 DLL的加载与连接

Windows DLL装入(除ntdll.dll外)和连接是通过ntdll.dll中一个函数LdrInitializeThunk实现的。先对LdrInitializeThunk()这个函数名作些解释“Ldr显然是“Loader”的缩写。而“Thunk”意为“翻译”、“转换”、或者某种起着“桥梁”作用的东西。这个词在一般的字典中是查不到的,但却是个常见于微软的资料、文档中术语。这个术语起源于编译技术,表示一小片旨在获取某个地址的代码,最初用于函数调用时“形参”和“实参”结合。后来这个术语有了不少新的特殊含义和使用,但是DLL的动态连接与函数调用时“形实结合”确实有着本质的相似。

DLL文件中包含一个导出函数表。这些导出函数由它们的符号名和称为标识号的整数与外界联系起来。函数表中还包含了DLL中函数的地址。当应用程序加载DLL模块时时,它并不知道调用函数的实际地址,但它知道函数的符号名和标识号。动态链接过程在加载的DLL模块时动态建立一个函数调用与函数地址的对应表。如果重新编译和重建DLL文件,并不需要修改应用程序,除非你改变了导出函数的符号名和参数序列。

5 DLL注册及为什么需要注册?

在系统故障中,有很多都是由于DLL文件丢失、损坏或没有注册造成的,比如Windows XP的压缩文件夹功能出现故障就很有可能是系统目录中的zipfldr.dll没有注册造成的,这类故障的解决方法也大多是下载一个对应的DLL并运行如下命令:

for%1 in (%windir%system32*.dll)do regsvr32.exe /s %1

很多人不理解为什么要这么做,是不是所有的DLL都能这样做呢?

其实系统中有两种DLL,一种是不需注册即可使用的,另一种则是必须经过注册才能使用的。就好像一个临时工,和一个记录在员工名单上的长期合同工的区别一样。如何才能区分这两种DLL呢?方法很简单,可以用一个工具(如Dependency Walker)打开这个DLL,看函数输出表,如果其中包含以下两个函数(前者是注册DLL,后者是反注册DLL),那么就一定是需要注册才能使用的DLL了。

DllRegisterServer

DllUnregisterServer

而regsvr32这个命令,实际上就是调用DLL中的这两个函数(“regsvr32 /u DLL文件名”调用的即为DllUnregisterServer反注册函数)。

注册与不注册,.dll文件都在system32下面。不同的是,注册了会在注册表中有相应信息,同时载入到了dll缓存,没有注册信息和进缓存就不能使用(开机时操作系统的一些核心功能再加载到了内存,并开始在后台运行,程序、数据、模块都需要进入内存才能被访问。)。

文件注册前和注册后都没有变化,只是通过命令把相应的信息添加到了注册表中。

注册文件的命令行是 regsrv32

regsrv32 xxx.dll

regsrv32 xxx.dll /u

regsvr32 [/u] [/s] [/n] [/i[:cmdline]] dllname

参数说明:

/u - 解除服务器注册

/s - 无声;不显示消息框

/i - 调用 DllInstall,给其传递一个可选 [cmdline];跟 /u 一起使用时,卸载 dll

/n - 不要调用 DllRegisterServer;这个选项必须跟 /i 一起使用

-End-返回搜狐,查看更多


相关推荐

基本字义解释
是是、非非谓之知,非是、是非谓之愚。
王者荣耀:阿珂对位猴子的2个技巧,学会后,暴打猴子
最初设计时就会避开钽电容,这是为什么呢?三大理由告诉你原因
库存管理系统软件哪个好用 盘点前十名!
如何在 iPhone 上设置和更改闹钟