| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> VC++通过查看ReactOS开源代码,解决完整路径dll加载失败问题(附源码) -> 正文阅读 |
|
[C++知识库]VC++通过查看ReactOS开源代码,解决完整路径dll加载失败问题(附源码) |
目录 3、到ReactOS开源代码中去查看regsvr32的实现,找到解决问题的线索 3.2、使用Source Insight打开ReactOS源码,找到regsvr32.exe程序的代码 4、到微软MSDN上查看LOAD_WITH_ALTERED_SEARCH_PATH参数的含义 ? ? ? ?在某些情况下我们需要调用LoadLibrary动态地加载dll库,去获取dll库中的接口。但有时会出现加载失败的情况,即使传入的是dll库的全路径,也会加载失败,我们在项目中已经不止一次遇到这样的问题了。今天我们就来看一下这个问题该如何解决。 1、问题实例? ? ? ?我们通过代码去制作安装包,不再使用inno setup、installshield等打包工具,安装包中的文件拷贝、读写注册表、注册控件等操作都是通过代码去完成的。在某次测试时发现,某个控件注册失败了,注册控件的代码如下所示:
代码中通过dll文件的完整路径去加载控件dll,然后获取控件dll中的DllRegisterServer接口,调用DllRegisterServer接口完成控件的注册。 ? ? ? ? 根据打印出来的日志,在调用LoadLibrary去加载控件dll库时就失败了,我们给LoadLibrary接口传入的是控件dll的完整路径,到这个路径中也是能找到这个控件dll文件的。这个就有点搞不懂了,明明传入的是控件dll完整路径,并且控件dll文件在路径中也是存在的,为啥还会出现dll库加载失败的情况呢?这个有点太诡异了! 2、到cmd.exe中用regsvr32去手动注册控件? ? ? ?安装包程序无法加载该dll库,我们想到可以尝试到cmd窗口中,使用regsvr32去手动注册这个dll控件试试。打开cmd窗口,手动将dll文件拖入到cmd窗口中获取dll文件的路径,按下回车键去注册该控件:(此处以飞秋的ImageOle.dll控件为例来说明)
手动注册是能正常注册成功的。使用regsvr32去手动注册时,调用的是系统的regsvr32.exe程序,regsvr32.exe程序内部应该也需要去加载这个控件dll文件的,regsvr32.exe程序能成功将库加载起来的。难道regsvr32.exe程序加载库的方式,和我们安装包程序使用的方式不一样? 3、到ReactOS开源代码中去查看regsvr32的实现,找到解决问题的线索? ? ? ?之前下载过开源操作系统ReactOS的源码,ReactOS中的系统库内部实现和Windows是很相像的,提供的系统API接口基本是一模一样的。我们时常会去查看ReactOS中API函数及底层库的内部实现,去了解Windows系统的内部实现,以辅助排查我们在开发过程中遇到的问题。 3.1、ReactOS开源操作系统简介? ? ? ?ReactOS是一款基于 Windows NT 架构的类似于Windows XP系统的免费开源操作系统,旨在实现和 NT 与 Windows 操作系统二进制下的完全应用程序和驱动设备的兼容性,通过使用类似构架和提供完全公共接口。 ? ? ? ?ReactOS开源代码对于我们Windows软件开发人员来说非常有用,我们可以去查看API函数的内部实现,可以去查看系统exe的内部实现,可以去查看ReactOS系统内部任意模块的实现代码。ReactOS是比较接近Windows系统的,可以通过查看ReactOS的代码去大概地了解Windows系统的内部实现,对我们排查Windows软件的问题是很有好处的! 3.2、使用Source Insight打开ReactOS源码,找到regsvr32.exe程序的代码? ? ? ?ReactOS源码中没有Visual Studio工程文件,无法使用Visual Studio打开查看源代码,可以Source Insight去查看源码。至于怎么使用Source Insight,可以参看我之前写的一篇关于Source Insight的文章: 使用Source Insight查看编辑源代码https://blog.csdn.net/chenlycly/article/details/124347857因为regsvr32是一个独立的exe,不是一个函数,所以需要找到该程序对应的.c源文件。于是尝试到文件列表中以regsvr32为关键字进行搜索,找到了regsvr32.c文件。在该文件中找到_tWinMain函数,在该main函数中看到了加载dll库文件的代码,如下所示: 代码中是调用LoadLibraryEx接口去加载dll库的,传入的参数为LOAD_WITH_ALTERED_SEARCH_PATH,并且也是获取dll控件库中的DllRegisterServer去进行注册的。 ? ? ? ? regsvr32.exe使用这种方式去加载库文件应该是有它的道理的,于是我们也参照它的做法,把加载dll库的代码改成调用LoadLibraryEx,传入LOAD_WITH_ALTERED_SEARCH_PATH,即如下所示:
改成上述代码后,就没再出现库加载失败的问题了,上述代码果然很有用啊! ? ? ? ?后来其他模块中也遇到库加载失败的问题,也更换成上述代码,结果后面再也没有出过问题了。这个通过库的绝对路径去加载库失败的问题,不是必现的,只是在个别机器上才会出问题。 4、到微软MSDN上查看LOAD_WITH_ALTERED_SEARCH_PATH参数的含义? ? ? ?为了搞清楚LOAD_WITH_ALTERED_SEARCH_PATH参数的含义,我们到微软MSDN上查看LoadLibraryEx API函数的说明页面,找到了LOAD_WITH_ALTERED_SEARCH_PATH参数的说明:
从上述描述文字得知,如果设置了LOAD_WITH_ALTERED_SEARCH_PATH参数,则系统会使用the alternate file search strategy搜索策略,那这个搜索策略到底是什么样的呢? ? ? ? ?在LoadLibraryEx函数的说明页面继续向下看,看到了"Dynamic-Link?Library?Search?Order"超链接,这是动态连接库加载顺序的详细说明页面。从页面中我们看到了,如果没设置LOAD_WITH_ALTERED_SEARCH_PATH参数,则使用Standard Search Order for Desktop Applications标准搜索顺序:
? ? ? ? 如果设置了LOAD_WITH_ALTERED_SEARCH_PATH参数,则系统会使用Alternate Search Order for Desktop Applications搜索顺序:
所以我们最终找到了答案,当我们设置LOAD_WITH_ALTERED_SEARCH_PATH参数时,就会使用Alternate Search Order for Desktop Applications,会优先使用设置下来的完整路径去加载dll库的。 |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 21:56:18- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |