当前位置: 首页 > news >正文

dll搜索顺序

一个系统可以包含同一动态链接库(DLL)的多个版本。应用程序可以通过指定完整路径或使用其他机制(如清单)来控制DLL的加载位置。如果未使用这些方法,则系统将如本主题中所述在加载时搜索DLL。

影响搜索的因素

以下因素影响系统是否搜索DLL:

  • 如果具有相同模块名称的DLL已在内存中加载,则系统在解析到已加载的DLL之前,仅检查重定向和清单,无论它位于哪个目录中。系统都不会搜索该DLL。
  • 如果该DLL在运行该应用程序的Windows版本的已知DLL列表中,则系统将使用其已知DLL(以及已知DLL的从属DLL,如果有)的副本代替搜索DLL。有关当前系统上已知DLL的列表,请参见以下注册表项:HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Session Manager \ KnownDLLs
  • 如果DLL具有依赖项,则系统将搜索依赖的DLL,就好像它们仅使用其模块名加载一样。即使通过指定完整路径加载了第一个DLL,也是如此。

搜索UWP(Universal Windows Platform)应用的订单

当Windows 10的UWP应用程序(或Windows 8.x的Store应用程序)通过调用LoadPackagedLibrary函数加载打包的模块时,DLL必须位于进程的程序包依赖关系图中。有关更多信息,请参见LoadPackagedLibrary。当UWP应用通过其他方式加载模块且未指定完整路径时,系统将如本节所述在加载时搜索DLL及其依赖项。

在系统搜索DLL之前,它会检查以下内容:

  • 如果内存中已经加载了具有相同模块名称的DLL,则系统将使用已加载的DLL,无论它位于哪个目录中。系统都不会搜索该DLL。
  • 如果该DLL在运行该应用程序的Windows版本的已知DLL列表中,则系统使用其已知DLL的副本(以及已知DLL的从属DLL,如果有的话)。系统不搜索DLL。有关当前系统上已知DLL的列表,请参见以下注册表项:HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Session Manager \ KnownDLLs

如果系统必须搜索模块或其依赖项,则即使依赖项不是UWP应用程序代码,它也始终使用UWP应用程序的搜索顺序。

UWP应用的标准搜索顺序

如果模块尚未加载或在已知DLL列表中,则系统将按以下顺序搜索这些位置:

  1. 程序的程序包依赖关系图。这是应用程序的包加上指定为任何依赖<PackageDependency><Dependencies>应用程序的软件包清单的部分。按照它们在清单中出现的顺序搜索依赖关系。
  2. 调用进程从中加载的目录。
  3. 系统目录(%SystemRoot%\ system32)。

如果DLL具有依赖项,则系统将搜索依赖的DLL,就好像它们仅使用其模块名加载一样。即使通过指定完整路径加载了第一个DLL,也是如此。

UWP应用的替代搜索顺序

如果模块通过使用LOAD_WITH_ALTERED_SEARCH_PATH调用LoadLibraryEx函数来更改标准搜索顺序,则系统将搜索指定模块的加载目录,而不是调用进程的目录。系统按以下顺序搜索这些位置:

  1. 程序的程序包依赖关系图。这是应用程序的包加上指定为任何依赖<PackageDependency><Dependencies>应用程序的软件包清单的部分。按照它们在清单中出现的顺序搜索依赖关系。
  2. 指定模块的加载目录。
  3. 系统目录(%SystemRoot%\ system32)。

桌面应用程序的搜索顺序

桌面应用程序可以通过指定完整路径,使用DLL重定向或使用manifest来控制DLL的加载位置。如果未使用这些方法,则系统将如本节所述在加载时搜索DLL。

在系统搜索DLL之前,它会检查以下内容:

  1. 如果内存中已经加载了具有相同模块名称的DLL,则系统将使用已加载的DLL,无论它位于哪个目录中。系统都不会搜索该DLL。
  2. 如果该DLL在运行该应用程序的Windows版本的已知DLL列表中,则系统使用其已知DLL的副本(以及已知DLL的从属DLL,如果有的话)。系统不搜索DLL。有关当前系统上已知DLL的列表,请参见以下注册表项:HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Session Manager \ KnownDLLs

如果DLL具有依赖项,则系统将搜索依赖的DLL,就好像它们仅使用其模块名加载一样。即使通过指定完整路径加载了第一个DLL,也是如此。

重要

如果攻击者获得了对所搜索目录之一的控制,则可以将DLL的恶意副本放置在该目录中。有关防止此类攻击的方法,请参见Dynamic-Link Library Security。

桌面应用程序的标准搜索顺序

系统使用的标准DLL搜索顺序取决于是否启用安全DLL搜索模式安全DLL搜索模式将用户的当前目录放在搜索顺序的后面。

默认情况下,安全DLL搜索模式处于启用状态。若要禁用此功能,请创建HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session Manager \ SafeDllSearchMode注册表值并将其设置为0。当指定目录在搜索路径中时,调用SetDllDirectory函数可有效禁用SafeDllSearchMode并按照说明更改搜索顺序在本主题中。

如果启用了SafeDllSearchMode,则搜索顺序如下:

  1. 从加载应用程序的目录中。
  2. 系统目录。使用GetSystemDirectory函数获取此目录的路径。
  3. 16位系统目录。没有获取该目录路径的函数,但会对其进行搜索。
  4. Windows目录。使用GetWindowsDirectory函数获取此目录的路径。
  5. 当前目录
  6. PATH环境变量中列出的目录。请注意,这不包括App Paths注册表项指定的每个应用程序路径。计算DLL搜索路径时不使用App Paths键。

如果禁用SafeDllSearchMode,则搜索顺序如下:

  1. 从加载应用程序的目录中。
  2. 当前目录。
  3. 系统目录。使用GetSystemDirectory函数获取此目录的路径。
  4. 16位系统目录。没有获取该目录路径的函数,但会对其进行搜索。
  5. Windows目录。使用GetWindowsDirectory函数获取此目录的路径。
  6. PATH环境变量中列出的目录。请注意,这不包括App Paths注册表项指定的每个应用程序路径。计算DLL搜索路径时不使用App Paths键。

桌面应用程序的替代搜索顺序

通过使用LOAD_WITH_ALTERED_SEARCH_PATH(将这个标志加到LoadLibraryEx中)调用LoadLibraryEx函数,可以更改系统使用的标准搜索顺序。可以通过调用SetDllDirectory函数来更改标准搜索顺序。

备注

在当前进程开始之前,通过在父进程中调用SetDllDirectory函数也将影响该进程的标准搜索顺序。

如果指定备用搜索策略,则其行为将一直持续到找到所有关联的可执行模块为止。系统开始处理DLL初始化例程后,系统将还原为标准搜索策略。

如果调用指定LOAD_WITH_ALTERED_SEARCH_PATHlpFileName参数指定绝对路径,则LoadLibraryEx函数支持备用搜索顺序。

请注意,LoadLibraryEx使用LOAD_WITH_ALTERED_SEARCH_PATH指定的标准搜索策略和替代搜索策略只有一种不同:标准搜索从调用应用程序的目录开始,替代搜索从LoadLibraryEx正在加载的可执行模块的目录开始。

如果启用了SafeDllSearchMode,则备用搜索顺序如下:

  1. lpFileName指定的目录。
  2. 系统目录。使用GetSystemDirectory函数获取此目录的路径。
  3. 16位系统目录。没有获取该目录路径的函数,但会对其进行搜索。
  4. Windows目录。使用GetWindowsDirectory函数获取此目录的路径。
  5. 当前目录。
  6. PATH环境变量中列出的目录。请注意,这不包括App Paths注册表项指定的每个应用程序路径。计算DLL搜索路径时不使用App Paths键。

如果SafeDllSearchMode被禁用,则替代搜索顺序如下:

  1. lpFileName指定的目录。
  2. 当前目录。
  3. 系统目录。使用GetSystemDirectory函数获取此目录的路径。
  4. 16位系统目录。没有获取该目录路径的函数,但会对其进行搜索。
  5. Windows目录。使用GetWindowsDirectory函数获取此目录的路径。
  6. PATH环境变量中列出的目录。请注意,这不包括App Paths注册表项指定的每个应用程序路径。计算DLL搜索路径时不使用App Paths键。

SetDllDirectory功能支持的替代搜索顺序如果lpPathName参数指定的路径。备用搜索顺序如下:

  1. 从加载应用程序的目录中。
  2. 由SetDllDirectory的lpPathName参数指定的目录。
  3. 系统目录。使用GetSystemDirectory函数获取此目录的路径。该目录的名称是System32。
  4. 16位系统目录。没有获取该目录路径的函数,但会对其进行搜索。该目录的名称是System。
  5. Windows目录。使用GetWindowsDirectory函数获取此目录的路径。
  6. PATH环境变量中列出的目录。请注意,这不包括App Paths注册表项指定的每个应用程序路径。计算DLL搜索路径时不使用App Paths键。

如果lpPathName参数为空字符串,则该调用将从搜索顺序中删除当前目录。

当指定目录位于搜索路径中时, SetDllDirectory有效地禁用安全DLL搜索模式。要恢复基于安全DLL搜索模式SafeDllSearchMode注册表值,并恢复当前目录搜索顺序,调用SetDllDirectory会lpPathName为NULL。

使用LOAD_LIBRARY_SEARCH标志的搜索顺序

应用程序可以通过将一个或多个LOAD_LIBRARY_SEARCH标志与LoadLibraryEx函数一起使用来指定搜索顺序。应用程序还可以将LOAD_LIBRARY_SEARCH标志与SetDefaultDllDirectories函数一起使用,以建立进程的DLL搜索顺序。应用程序可以使用AddDllDirectory或SetDllDirectory函数为进程DLL搜索顺序指定其他目录。

搜索的目录取决于SetDefaultDllDirectories或LoadLibraryEx指定的标志。如果使用多个标志,则按以下顺序搜索相应的目录:

  1. 包含DLL的目录(LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR)。仅在此目录中搜索要加载的DLL的依赖项。
  2. 应用程序目录(LOAD_LIBRARY_SEARCH_APPLICATION_DIR)。
  3. 使用AddDllDirectory函数(LOAD_LIBRARY_SEARCH_USER_DIRS)或SetDllDirectory函数显式添加的路径。如果添加了多个路径,则未指定搜索路径的顺序。
  4. 系统目录(LOAD_LIBRARY_SEARCH_SYSTEM32)。

如果应用程序未使用任何LOAD_LIBRARY_SEARCH标志调用LoadLibraryEx或未为该过程建立DLL搜索顺序,则系统将使用标准搜索顺序或替代搜索顺序搜索DLL。

相关文章:

  • 嵌入V8入门
  • V8编程详解
  • 代理服务器
  • sqlite加密
  • x86/x64/x86_64/i386/ia32/ia64/amd/amd64 辨析
  • 理清gcc、libc、libstdc++的关系
  • gcc/g++/clang/cl编译器
  • 深入浅出让你理解什么是LLVM
  • Ninja - chromium核心构建工具
  • depot_tools
  • 智能指针 unique_ptr 详解
  • C++11中“= delete;“的使用
  • C++Error2208:...尝试引用已删除的函数
  • Ninja 构建系统
  • ICU
  • [译] React v16.8: 含有Hooks的版本
  • 《剑指offer》分解让复杂问题更简单
  • ES6简单总结(搭配简单的讲解和小案例)
  • extract-text-webpack-plugin用法
  • GitUp, 你不可错过的秀外慧中的git工具
  • Intervention/image 图片处理扩展包的安装和使用
  • Java,console输出实时的转向GUI textbox
  • mongodb--安装和初步使用教程
  • node 版本过低
  • open-falcon 开发笔记(一):从零开始搭建虚拟服务器和监测环境
  • ucore操作系统实验笔记 - 重新理解中断
  • 安卓应用性能调试和优化经验分享
  • 线上 python http server profile 实践
  • 学习JavaScript数据结构与算法 — 树
  • 在Docker Swarm上部署Apache Storm:第1部分
  • NLPIR智能语义技术让大数据挖掘更简单
  • Prometheus VS InfluxDB
  • 阿里云服务器购买完整流程
  • 阿里云移动端播放器高级功能介绍
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第2章第五节(日期和时间)
  • (LeetCode C++)盛最多水的容器
  • (附源码)ssm码农论坛 毕业设计 231126
  • (转)EOS中账户、钱包和密钥的关系
  • (转)为C# Windows服务添加安装程序
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • .a文件和.so文件
  • .md即markdown文件的基本常用编写语法
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .NET Remoting学习笔记(三)信道
  • .net 按比例显示图片的缩略图
  • .net 开发怎么实现前后端分离_前后端分离:分离式开发和一体式发布
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)...
  • .net和jar包windows服务部署
  • ::before和::after 常见的用法
  • @ComponentScan比较
  • [ Linux Audio 篇 ] 音频开发入门基础知识