如何解决程序/C++Dll的兼容性问题

本文将尝试解决程序与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)在程序的安装程序中添加运行环境检测,给予没有必要运行环境的客户机强制安装必要的运行环境支持。

BY Sunyday丶若雪 转载请注明出处

综合项目之闪讯破解(六)之 如何解决程序/C++Dll的兼容性问题相关推荐

  1. java集合体检套餐管理系统_基于ssm vue的综合项目 健康体检管理系统-第六章

    移动端开发对体检预约进行的查询 当页面加载完毕时,利用vue的钩子函数 已加载页面就直接查询数据将数据进行渲染 created() { axios.post("/setmeal/getSet ...

  2. 基于ssm+vue的综合项目 健康体检管理系统-第六章---移动端体检预约

    移动端开发对体检预约进行的查询 当页面加载完毕时,利用vue的钩子函数 已加载页面就直接查询数据将数据进行渲染 created() {axios.post("/setmeal/getSetm ...

  3. “中软综合项目实训”——把学生当员工培养

    "中软综合项目实训"--把学生当员工培养 中软卓越大连ETC 2013年,对于中国IT职业教育界而言,一场教育模式变革的旋风已经悄然刮起. 在市场经济日益成熟的今天,"人 ...

  4. 闪讯客户端 linux,Linux操做系统下链接闪讯的方法(支持有线与无线)

    1.前言 用过电信闪讯的同窗都知道,闪讯没有开发Linux的客户端程序,因此这让不少玩Linux操做系统同时又是闪讯用户的同窗很头疼,今天我就来介绍一下如何在Linux下链接闪讯网络,而且支持有线链接 ...

  5. 闪讯路由器linux系统,Linux操作系统下连接闪讯的方法(支持有线与无线)

    一.前言 用过电信闪讯的同学都知道,闪讯没有开发Linux的客户端程序,所以这让很多玩Linux操作系统同时又是闪讯用户的同学很头疼,今天我就来介绍一下如何在Linux下连接闪讯网络,并且支持有线连接 ...

  6. linux系统的开发版连接wifi密码,Linux操作系统下连接闪讯的方法(支持有线与无线)...

    一.前言 用过电信闪讯的同学都知道,闪讯没有开发Linux的客户端程序,所以这让很多玩Linux操作系统同时又是闪讯用户的同学很头疼,今天我就来介绍一下如何在Linux下连接闪讯网络,并且支持有线连接 ...

  7. Linux操作系统下连接闪讯的方法(支持有线与无线)

    一.前言 用过电信闪讯的同学都知道,闪讯没有开发Linux的客户端程序,所以这让很多玩Linux操作系统同时又是闪讯用户的同学很头疼,今天我就来介绍一下如何在Linux下连接闪讯网络,并且支持有线连接 ...

  8. 树莓派python交互界面实例_树莓派综合项目2:智能小车(二)tkinter图形界面控制...

    一.介绍 树莓派综合项目2:智能小车(一)四轮驱动中,实现了代码输入对四个电机的简单控制,本章将使用Python 的图形开发界面的库--Tkinter 模块(Tk 接口),编写本地运行的图形界面,控制 ...

  9. Android App 可以定时启动! 并且完成短信自动发送获取内容功能 (以获取闪讯密码为例 大学宿舍宽带)

    接上一篇:android 发送短信sendTextMessage()真机运行报错,退出,在已申请SEND_SMS权限的情况下Android send SMS not working uid ... 重 ...

  10. Android App 可以定时启动! 并且完成短信自动发送获取内容功能 (以获取闪讯密码为例 大学宿舍宽带)

    接上一篇:android 发送短信sendTextMessage()真机运行报错,退出,在已申请SEND_SMS权限的情况下Android send SMS not working uid ... 重 ...

最新文章

  1. vijos - P1279Leave-绿光(数学归纳法 + python)
  2. 同一账户同时只能在一处登陆(单点登陆)
  3. equal_range
  4. Java 集合List、Set、HashMap操作一(Array转List、Set排序、HashMap遍历、Set遍历、List遍历、HashMap大小长度、List打乱顺序)
  5. 深入掌握JMS(二):一个JMS例子
  6. 自定义exchange由IMF导致的NDR信息
  7. 程序员又惹祸!B站网站后台工程源码泄露 内含部分用户名密码
  8. 清华大学发布《人工智能芯片技术白皮书(2018)》
  9. Qt-QThread
  10. select into from 和 insert into select 的用法和区别
  11. win10下安装deepin双系统教程
  12. 使用GitLab CI/CD进行自动测试和部署
  13. 论文分享(一) CVPR 2018 Defense against Universal Adversarial Perturbations
  14. CocosCreator开场CG动画制作
  15. java中cbrt_JavaScript中带有示例的Math.cbrt()方法
  16. python怎么算反三角函数_python弧度制转换 三角函数 反三角函数 双曲 反双曲 sin cos tan asin acos atan asinh acosh atanh atanh2...
  17. Eureka 健康检查
  18. 【linux】在linux上生成SSH-key 简单原理介绍+生成步骤
  19. dialog.show()不显示也不报错
  20. 产品思维考察之对象思维

热门文章

  1. C# - [实践] 电子词典
  2. 均匀面阵方向图仿真(七)
  3. android画板的实验报告,几何画板实验报告
  4. VS2017 插件的安装目录
  5. java正则表达式中的斜杠,java正则表达式匹配斜杠[Java编程]
  6. Java web项目目录结构以及作用详解
  7. 【阿里巴巴Java编程规范学习 二】Java基本编程规约(下)
  8. 用C语言求解合式公式的主合取范式和主析取范式
  9. ftp登录常用命令和工作模式简介
  10. DreamWeaver CS5视频教程(建站必备)