1.dll文件的依赖分析可以通过

使用64位的depends.exe查看你exe依赖的dll

2.32位dll和64位dll的查看

3.dll文件的搜索路径

作者:朱金灿
来源:http://blog.csdn.net/clever101/

DLL的动态链接有两种方法。一种是加载时动态链接(Load_time dynamic linking)。Windows搜索要装入的DLL时,按以下顺序:应用程序所在目录→当前目录→Windows SYSTEM目录→Windows目录→PATH环境变量指定的路径。

前天看到这几句,突然设计出一道自认绝妙的笔试题:
"如果采用加载时动态链接的方式,Windows搜索要装入的DLL采用怎样的顺序?"
这个是基础题,估计你很容易答出(答案就是上面的)。呵呵,我还有后着呢:
"你是如何证明Windows搜索要装入的DLL遵循这样的顺序呢,说出你的证明步骤"

你可以思考一下。下面是我设想的一个方案,但是自己测试了一下。结果却令人吃惊。

我的证明步骤是这样的:
1. 首先新建一个MFC 常规DLL工程OutputModulePath,在里面添加一个API函数,功能就是打印DLL所在路径,然后将其导出,代码如下:

[cpp] view plain copy
  1. void PaintModulePath()
  2. {
  3. extern COutputModulePathApp theApp;
  4. TCHAR szModulePath[MAX_PATH];
  5. :: GetModuleFileName(theApp.m_hInstance,szModulePath, MAX_PATH);
  6. AfxMessageBox(szModulePath);
  7. }

2. 编译这个DLL工程,然后将生成的DLL文件OutputModulePath.dll复制到当前目录、Windows SYSTEM目录→Windows目录→PATH环境变量指定的路径。这里要说明一下:如果调试运行的话,当前目录应该是当前目录的工程文件所在的路径,如果单击直接运行的话,当前目录应该是exe程序所在的路径,具体可以通过一下代码获取当前目录:

[cpp] view plain copy
  1. TCHAR szBuf[MAX_PATH];
  2. ::ZeroMemory(szBuf,MAX_PATH);
  3. if (::GetCurrentDirectory(MAX_PATH,szBuf) > 0)
  4. {
  5. //获取进程目录成功。
  6. AfxMessageBox(szBuf);
  7. }

PATH环境变量指定的路径这里可能有多个路径,这里只须将OutputModulePath.dll拷贝到其中之一就行,例如我拷贝到的是:D:/Program Files/Lua/5.1。

3. 建一个测试工程(对话框程序或单文档程序都可以),在里面调用PaintModulePath函数。
我的测试步骤及结果是这样的,按F5调试运行测试程序,首先程序输出的是exe程序所在的路径,然后我将exe程序路径下的dll文件删除,但接着输出的是C:/WINDOWS/system/OutputModulePath.dll,我将C:/WINDOWS/system/OutputModulePath.dll删除,接着输出的是C:/WINDOWS/ OutputModulePath.dll,将C:/WINDOWS/ OutputModulePath.dll删除,输出的才是当前目录下的文件路径,最后输出的是PATH环境变量指定的路径。

这样的结果和书上的理论不符。难道我的测试方案有什么不对吗?

到论坛一问,得到一个答案是微软上的一篇文章:

Dynamic-Link Library Search Order

现在把它翻译一下:

动态链接库的搜索顺序

一个系统可以包含多个版本的同一个动态链接库(dll)。应用程序能够通过使用动态链接库重定向或清单文件 指定要加载的DLL的全路径。如果没有使用这些方法,这篇文章将讲述在装入DLL时DLL的搜索顺序。

标准的搜索顺序

DLL的搜索顺序取决于是否安全DLL搜索模式是启用或禁用。
安全DLL搜索模式在默认状态下是启用的。通过创HKLM/System/CurrentControlSet/Control/Session Manager/SafeDllSearchMode注册表项并将它的值设为0可以关闭这个属性。通过调用SetDllDirectory函数可以有效禁用安全DLL搜索模式而在这篇文章中这个函数指定的路径将加入搜索范围并改变搜索顺序。

Windows XP and Windows 2000 with SP4: 安全DLL搜索模式在默认状态下是禁用的。通过创HKLM/System/CurrentControlSet/Control/Session Manager/SafeDllSearchMode注册表项并将它的值设为1可以启用这个属性。安全DLL搜索模式在默认状态下得到启用始于带sp2的Windows XP。

Windows 2000: 并不支持安全DLL搜索模式。在这种情况下DLL的搜索顺序和安全DLL搜索模式被禁用的情况下的顺序是一样的。安全DLL搜索模式得到支持始于带sp4的Windows 2000。

假如安全DLL搜索模式启用,搜索顺序如下:
1. 应用程序所在的路径
2. Windows SYSTEM目录。通过调用GetSystemDirectory函数可以获取这个目录的路径。
3. 16位系统的目录。并没有函数可以获取这个目录的路径,但是它会被查找。
4. Windows目录。通过调用GetWindowsDirectory函数可以获取这个目录的路径。
5. 当前目录
6. PATH环境变量指定的路径。请注意,这并不包括每个应用程序的应用程序路径注册表项中指定。在应用程序路径注册表项的键值并不作为DLL的搜索路径。

假如安全DLL搜索模式禁用,搜索顺序如下:
1. 应用程序所在的路径
2. 当前目录
3. Windows SYSTEM目录。通过调用GetSystemDirectory函数可以获取这个目录的路径。
4. 16位系统的目录。并没有函数可以获取这个目录的路径,但是它会被查找。
5. Windows目录。通过调用GetWindowsDirectory函数可以获取这个目录的路径。
6. PATH环境变量指定的路径。请注意,这并不包括每个应用程序的应用程序路径注册表项中指定。在应用程序路径注册表项的键值并不作为DLL的搜索路径。

预备的搜索顺序

由系统指定的标准搜索顺序可以通过调用LoadLibraryEx函数加上LOAD_WITH_ALTERED_SEARCH_PATH参数值得到改变。标准搜索顺序也可以通过调用SetDllDirectory函数得到改变。

Windows XP: 通过调用SetDllDirectory函数来改变标准搜索顺序并不支持直到Windows XP sp1出现。
Windows 2000: 不支持通过调用SetDllDirectory函数来改变标准搜索顺序。

如果您指定一个备用的搜索顺序,程序将按备用的搜索顺序进行搜索,直到所有相关的可执行模块被找到。系统启动后,DLL初始化例程处理,该系统将恢复为标准的搜索顺序。

LoadLibraryEx函数通过指定LOAD_WITH_ALTERED_SEARCH_PATH属性和lpFileName参数指定一个绝对路径支持一个预备的搜索顺序。

请注意:标准搜索顺序和通过调用指定LOAD_WITH_ALTERED_SEARCH_PATH属性的LoadLibraryEx函数来设置的预备搜索顺序只是有一点不同:标准搜索顺序开始于搜索1. 应用程序所在的路径而预备搜索顺序开始于LoadLibraryEx函数所要加载的可执行模块的所在目录。

假如安全DLL搜索模式启用,搜索顺序如下:

1. lpFileName参数值所指定的目录
2. Windows SYSTEM目录。通过调用GetSystemDirectory函数可以获取这个目录的路径。
3. 16位系统的目录。并没有函数可以获取这个目录的路径,但是它会被查找。
4. Windows目录。通过调用GetWindowsDirectory函数可以获取这个目录的路径。
5. 当前目录
6. PATH环境变量指定的路径。请注意,这并不包括每个应用程序的应用程序路径注册表项中指定。在应用程序路径注册表项的键值并不作为DLL的搜索路径。

假如安全DLL搜索模式禁用,搜索顺序如下:

1. lpFileName参数值所指定的目录
2. 当前目录
3. Windows SYSTEM目录。通过调用GetSystemDirectory函数可以获取这个目录的路径。
4. 16位系统的目录。并没有函数可以获取这个目录的路径,但是它会被查找。
5. Windows目录。通过调用GetWindowsDirectory函数可以获取这个目录的路径。
6. PATH环境变量指定的路径。请注意,这并不包括每个应用程序的应用程序路径注册表项中指定。在应用程序路径注册表项的键值并不作为DLL的搜索路径。

假如lpPathName参数指定了一个路径,SetDllDirectory函数支持一个预备的搜索顺序。这个预备的搜索顺序如下:

1. 应用程序所在的路径
2. lpPathName参数指定的目录
3. Windows SYSTEM目录。通过调用GetSystemDirectory函数可以获取这个目录的路径。
4. 16位系统的目录。并没有函数可以获取这个目录的路径,但是它会被查找。
5. Windows目录。通过调用GetWindowsDirectory函数可以获取这个目录的路径。
6. PATH环境变量指定的路径。请注意,这并不包括每个应用程序的应用程序路径注册表项中指定。在应用程序路径注册表项的键值并不作为DLL的搜索路径。

如果lpPathName参数为一个空字符串,当前目录将会从搜索顺序中删除。
SetDllDirectory 有效地禁用安全DLL搜索模式,而在搜索指定的目录路径。要恢复安全 DLL搜索模式的SafeDllSearchMode注册表值的基础和恢复当前目录到搜索顺序,调用 lpPathName的参数值为NULL的SetDllDirectory函数。

看完这篇文章,我大致知道了我的测试为何会出现那个结果,因为我的操作系统环境是Win XP + sp3。

参考文献:

1. MFC深入浅出

可执行程序dll的依赖分析,dll文件32/64区分,dll的搜索路径相关推荐

  1. python import sql脚本_13-模块介绍-import两种方式-py文件的两种用途-模块搜索路径-项目开发的目录规范...

    1.模块的介绍与使用模块import 1.1.模块的介绍 1.1.1.什么是模块? 模块就是一组功能的集合体,我们的程序可以导入模块来复用模块里的功能.在python中,模块的使用方式都是一样的,但其 ...

  2. python-模块入门二(模块循环导入,区分python文件的两种用途,模块搜索路径,软件开发的目录规范)...

    一.模块的循环导入问题 run.py # import m1 # 第一次导入 m1.py # 错误示范 ''' print('正在导入m1') from m2 import y #第一次导入m2 x= ...

  3. C和C++中include 搜索路径的一般形式以及gcc搜索头文件的路径

    C和C++中include 搜索路径的一般形式 对于include 搜索的路径: C中可以通过 #include <stdio.h> 和 #include "stidio.h&q ...

  4. dll文件32位64位检测工具以及Windows文件夹SysWow64的坑

    自从操作系统升级到64位以后,就要不断的需要面对32位.64位的问题.相信有很多人并不是很清楚32位程序与64位程序的区别,以及Program Files (x86),Program Files的区别 ...

  5. c++:dll缺少依赖文件的解决方法

    c++:dll缺少依赖文件的解决方法 在A电脑上编译的dll可以在A运行,但是到B就不能运行了, 多数情况下是因为dll依赖于一些文件,这些文件存在于A,但是不存在于B. 所以我们需要在A上找到dll ...

  6. vs:dll缺少依赖文件的解决方法

    在运行程序时,一直出现dll缺少依赖文件的问题,解决方法: 把自己opencv文件目录下的\opencv\build\x64\vc15\bin中的三个dll文件,拷贝到C:\Windows\Syste ...

  7. java 加载dll后打包_让Jacob从当前路径读取dll文件及相关打包方法

    让Jacob从当前路径读取dll文件及相关打包方法 独立观察员2013.08.12 Jacob  LibraryLoader.class修改版代码 功能:让jacob可在当前路径下的dll文件夹内读取 ...

  8. 计算机中丢失cg,【计算机中丢失dll文件】计算机丢失dll文件_计算机中丢失cg dll-win7之家...

    2017-05-16 00:00:00 浏览量:489 wpcap.dll是一个高层的强大捕获程序库,与Unix下的libpcap兼容.它独立于下层的网络硬件和操作系统文件下载,解决找不到wpcap. ...

  9. 3601-lpk.dll劫持病毒分析

    文章目录 3601-lpk.dll劫持病毒分析 1.样本概况 1.1 样本信息 1.2 测试环境及工具 1.3 分析目标 1.4 样本行为概述 2.具体行为分析 2.1 主要行为 2.2 提取恶意代码 ...

最新文章

  1. WinXP不能共享Win7的打印机的解决方法
  2. 搭建 Hadoop 伪分布式环境
  3. Java 开发者必备手册开放下载!
  4. 2016 Multi-University Training Contest 3
  5. Android使用GestureDetector实现手势滑动效果
  6. sqlserver2005分布式架构负载
  7. hadoop3 禁用ec_Hadoop + Amazon EC2 –更新的教程
  8. gcc/g++ 链接库的编译与链接
  9. 大数据之-Hadoop3.x_MapReduce_序列化案例需求分析---大数据之hadoop3.x工作笔记0096
  10. CTR学习笔记代码实现1-深度学习的前奏LR-FFM
  11. Apollo应用接入
  12. Html文本域介绍,html文本域标签属性有哪些?html文本域标签属性用法介绍
  13. 从eclips到idea
  14. 负载均衡一致性哈希算法实现 | nginx 负载均衡一致性哈希源码分析 | ngx_http_upstream_consistent_hash_module 源码分析
  15. PHP取整,四舍五入取整、向上取整、向下取整、小数截取
  16. linux上最好的p图软件,10款好用的手机P图软件排行榜
  17. 【canvas绘制图形】
  18. matlab电流可逆斩波电路,电流可逆斩波电路.PPT
  19. 合理应用对阿斯克码值进行类型转换(尽量别用强制类型转换)
  20. 2. C++ Visual Studio中同一个项目包含多个有main函数的源文件怎么分别运行?

热门文章

  1. 计算机网络4个要素,所谓计算机网络,就是计算机网络的定义涉及到以下哪四个要点...
  2. CSR mascon产品深度解析
  3. blt功能_bitblt()用法
  4. php博客怎么上线,老张博客上线啦(二)
  5. Windows11 22H2将文件传输速度减慢了40% 如何解决?
  6. 苹果显示4g却上不了网_苹果 iPhone 12 在智能数据模式下,显示 5G 实测可能是 4G...
  7. 响铃:百度图腾要做正版授权平台,它能解决图片版权双向痛点吗?
  8. 一个保险柜密码是三位数,对上其中两位就可以打开,最坏至少试多少次才能保证打开
  9. 关于C++中有符号整型和无符号整型的转换方法
  10. 卡片布局 java_Java Swing CardLayout卡片布局的实现示例