如何解决程序/C++Dll的兼容性问题
2016-11-22 14:47
218 查看
如何解决程序/C++Dll的兼容性问题
转载出处 原文网址 BY Sunyday丶若雪
本文将尝试解决程序与DLL在不同客户机上运行存在的兼容性问题
前言
前面的五篇文章已经将程序的核心部分全部搞定,由于我们调用了一些系统API,所以这很有可能导致程序在其他不同的客户机上无法正确运行。其实关于程序的兼容性提高在之前选择到底使用何种方法来实现某一功能时已经相当于做过一次了,由于所有的核心功能都是封装在C++DLL中的,那么C++DLL兼容性直接决定了程序的兼容性,所以提高C++DLL兼容性成为了至关重要的问题。
1)先尝试在目标客户机试运行
注意:在开发者的电脑上测试是绝对通过的,能在开发者电脑上测试通过不代表客户机能运行,由于开客户机不一定有开发者电脑的大量程序运行必要的支持框架和组件,所以先要弄清楚程序需要哪些支持框架、组件、Dll,然后再搞清哪些支持框架是客户机肯定拥有的,哪些是客户机不一定拥有的要在客户机上测试,那么什么样的客户机是合理的:
Windows操作系统,这是必须的
编写程序界面的语言是C#,编写程序核心的语言是C++,两种语言都需要Microsoft .NET Framework的支持,由于这个程序在编写当初就没有想支持XP的意思,所以这两种语言都选用了Microsoft .NET Framework 4.5版本(XP最高支持到Microsoft .NET Framework 3.0),其实Microsoft .NET Framework 4.5算是客户机上必有的支持框架了。
大概现在就知道需要这个了,于是打开VM新建一个虚拟机,安装WIN7,再装入一个Microsoft .NET Framework 4.5支持框架,把程序拷贝进去,启动。
由于程序启动不用调用DLL.dll所以程序界面是可以打开的,继续测试功能,单击“连接”。
明明已经把DLL.dll放到了程序运行目录下,但它还是提示找不到指定模块DLL.dll
这个提示并不是找不到DLL.dll,其实是想表明DLL.dll所引用的DLL找不到,那么必须弄清楚这个DLL.dll还引用了什么其他DLL
2)查看DLL.dll引用了哪些DLL
用DLL函数查看器打开编写的DLL 查看DLL的引用,将DLL的引用信息输出TXT文件查看
这里显示一共引用了5个DLL,功能分别是:
系统支持的:
wlanapi.DLL:管理WLAN的系统DLL
RASAPI32.DLL:管理拨号的系统DLL
KERNEL32.DLL:系统内核DLL
Visual Studio 2015 C++支持的:
VCRUNTIME140.DLL:Visual Studio 2015 生成的 C++ 应用程序所需的运行时组件。
api-ms-win-crt-runtime-l1-1-0.dll:Visual Studio 2015 生成的 C++ 应用程序所需的运行时组件。
注:安装Visual C++ Redistributable Package就会为Visual Studio 2015 C++ 生成的 C++ 应用提供运行支持
通过上面的DLL分类大概可知是由于DLL.dll找不到Visual Studio 2015支持的两个DLL导致的
依据我们的DLL引用DLL时的路径寻找方法(在上一篇文章中提到过),只要把这两个DLL放到和DLL.dll相同目录下应该就OK了。
3)依据引用的DLL名称尝试找出被引用的DLL
在C盘搜索VCRUNTIME140.DLL,结果如下:竟然有么多,这就很尴尬了,怎么确定它调用的是哪个
没办法,只能再上一个软件procexp64_V16.02(进程查看器),他可以看到所有进程调用的所有DLL以及这些被调用的DLL的位置
在开发者电脑上启动“闪讯破解”
打开procexp64_V16.02,找到“闪讯破解”,按下Ctrl+D显示闪讯破解所调用的DLL的信息
在这里只找到了VCRUNTIME140.DLL没有找到api-ms-win-crt-runtime-l1-1-0.dll;先根据procexp64_V16.02的DLL路径显示拷贝VCRUNTIME140.DLL到虚拟机应用程序下;由于没有找到api-ms-win-crt-runtime-l1-1-0.dll的真实调用路径,只能是去C盘搜索这个DLL然后随便拷贝一个过来试试了。
现在能确定系统支持的3个DLL和VCRUNTIME140.DLL是没有问题的,只能尝试运行程序
果然报错了,这次不是”找不到指定模块了“而是“试图加载不正确的程序”,这是由于引用了不正确的DLL导致的,估计就是api-ms-win-crt-runtime-l1-1-0.dll出问题了。但是毕竟C盘有这么多api-ms-win-crt-runtime-l1-1-0.dll,总不可能都一一拷贝过来尝试,看来只能另寻他法了。
4)使用静态编译生成DLL
右键点击DLL项目名,打开DLL项目属性配置属性–C/C++–代码生成–运行库
这里的运行库有4个选项:
后面的那个’d’是代表DEBUG版本,没有’d’的就是RELEASE版本了
多线程MT的程序来说,其连接的是libcmt.lib,该文件属于C语言运行时库,整个lib都会连接到PE文件当中。
多线程MD的程序链接的却是类似msvcpXXX.dll,该文件属于微软运行时库,也就是说如果是多线程MD编译出来的文件运行时都会加载相应版本的运行时库,当如果找不到运行时库就会报错而无法运行,同时如果运行时库不匹配也会出现各种意料之外的崩溃或者程序根本跑不起来等情况。
从上面的说明可以看出由于使用的是MD方式编译,所以在运行时会调用更多的用于支持VS2015C++应用运行的DLL,为了减少调用DLL数量,选择MT编译。
注:千万不可以调用DEBUG的DLL,否则加载模块照常会出错。
选用MT后重新编译,用DLL查看器打开新生成的DLL,输出被引用DLL文件信息
发现关于VS2015的两个DLL都已经消失,只剩下三个系统的DLL
拷贝到虚拟机,尝试
单击”连接“按钮后如果能成功引用DLL中的函数,程序会进行编辑框输入文本检验
程序成功的引用了DLL中的函数,进行了编辑框输入文本检验
同时也发现,新编译的DLL大小变大了许多
5)使用 多线程MT 方式编译的弊端
成功运行程序后发现DLL变大了许多,这样就不是很好了,这是由于多线程MT编译的时候整个lib都会编译到DLL文件当中导致的。其实多线程MT编译不单单是这种缺点:如果是通过多线程MT编译方式出来的程序,那么A模块中申请的内存到B模块中释放就会出现问题,这是非常致命的。其实绝大多数软件都是采用多线程MD方式编译,如果找到他们目录很容易发现上面提到的运行时库。因为这样一来编译出来的文件小,所有运行时库统一,同时也让内存管理简单化,省去了跨模块内存访问带来的各种bug。所以多线程MD还是很好用的,能不用多线程MT就不用。
6)如何才能让多线程MD方式编译的程序在客户机正常运行
在上面在解释引用DLL各自功能中就提到过,安装Visual C++ Redistributable Package就会为Visual Studio 2015 C++ 生成的 C++ 应用提供运行支持,x64和x86最好都装上,这样程序就可以在客户机上运行了
最后在说两句
如何提高程序的兼容性
1)对于程序所使用的编程语言的必要运行环境支持必须熟知,比如C#需要安装Microsoft .NET Framework X.X,C++需要安装Visual C++ Redistributable for Visual Studio XXXX(x64和x86)2)要学会使用DLL函数查看器、depends.exe、procexp64_V16.02来查看程序运行所依赖的dll,并不是所有客户机都有Visual C++ Redistributable for Visual Studio XXXX(x64和x86),把找到的正确的DLL直接加入程序目录。
3)在程序的安装程序中添加运行环境检测,给予没有必要运行环境的客户机强制安装必要的运行环境支持。
相关文章推荐
- 如何解决程序/C++Dll的兼容性问题
- 综合项目之闪讯破解(六)之 如何解决程序/C++Dll的兼容性问题
- Win7如何手动注册DLL文件以解决程序不能使用的问题
- 多线程 DLL 回调函数问题,当应用程序退出时,有些操作并未完成,造成程序内存泄露,如何解决呢
- windows下如何解决PHP调用的外部程序超时阻塞问题
- 程序编码问题..如何设置引用控件支持字符编码.解决传参中编码问题
- 如何解决 SQL Server 安装程序中的 COM+ 系统配置检查失败问题
- 如何解决烦人的VS.NET2003编译时“无法将程序集复制到文件,另一个程序正在使用,进程无法访问”的问题?
- 调试时出现:“没有找到 MSVCR80D.dll,因此这个程序未能启动,重新安装应用程序,可能会修复此问题”错误提示,如何解决?
- 如何解决窗口和程序最小化后在任务栏消失的问题
- 近期的一些学习--当一个程序开发到了中期,突然出现性能问题,如何解决
- 如何有效解决C与C++的相互调用问题
- dll 释放时主程序最小化的问题解决
- missing type specifier - int assumed. Note: C++ does not support default-int,这是什么问题?如何解决呀?
- C++编译过程中"没有找到MFC80UD.DLL,因此这个程序未能启动.重新安装应用程序可能会修复此问题"? 的彻底解决
- 程序员最痛苦的事,就是程序出错;程序员最最痛苦的事,就是程序出错了还没有错误信息!--IIS Service Unavailable 问题如何解决
- 我是如何解决asp.net程序在dreamWeaver中布局乱码的问题
- 解决扩展MFC DLL与主程序资源冲突问题
- 如何解决新的发布,却出现读不到新的更新程序问题
- 这些天很忙,写一个类似防火墙的东西在WINSOCK2 SPI上做DLL,终于把问题解决了,现提供完整C++项目下载