当前位置: 代码迷 >> VC/MFC >> VC程序版本更新后一部分客户无法启动
  详细解决方案

VC程序版本更新后一部分客户无法启动

热度:310   发布时间:2016-05-02 03:55:20.0
VC程序版本更新后部分客户无法启动

VC程序版本更新后出现了部分用户无法启动程序的问题。
在开发机器上用Dependency Walker(http://www.dependencywalker.com)对比新旧版本,发现没有什么区别。
旧版本图1:


新版本图2:

因为大部分用户还是可以启动新程序的,所以用户的系统环境差异肯定是其中的一个重要原因。
1. 由于在Dependency Walker输出中看到了部分库文件是依赖系统winsxs下的运行库,根据上次处理类似问题的经验,先请运营发公告建议用户升级VC++ redistributable package,这解决了部分用户的问题;
2. 在QA某台XP测试机发现无法通过上一步的方法解决问题,通过在测试机上运行Dependency Walker,发现无法定位vc90的三个动态库。将新版本VC++ redistributable package中包含的这三个动态库复制到同一目录下,解决了这台机器的问题;于是安排更新包发布这三个文件,再解决一部分用户的问题。


问题还没有完全解决,原因都没找到呢!
因为有的用户同一台机器用旧版本可以启动,用新版本无法启动,所以版本之间的差异肯定也是原因之一。
因为前面两个步骤都有点效果,所以仍然怀疑同引用库有关。
用文本编辑器打开可执行文件,在文件末尾查找引用库清单(manifest)的版本信息:
旧版本图3:


新版本图4:

很明显找到原因了:新版本多引用了一个库:name="Microsoft.VC90.CRT" version="9.0.21022.8"。
这个版本号比旧版本程序的version="9.0.30729.1"版本旧,并且这两个版本号都低于我机器中实际引用到的库版本号"9.0.30729.6161"。
由于最近新增加了一个第三方库,所以很容易就定位到这个新库的manifest中引用到了这个低版本的运行库。
然后就修改第三方库的预定义宏配置,增加_BIND_TO_CURRENT_VCLIBS_VERSION宏后重新编译,我的机器编译出的结果是version="9.0.30729.4148",还是不同!
还好发布者的机器可以编译出version="9.0.30729.1"的库,用新库链接出的可执行文件也和旧版本的manifest一致了,问题完全解决!


老问题解决,新问题来了:为什么我机器上编译的版本号更高?
这个版本号应该是来自于不同的开发环境,于是检查VC环境,搜索包含"9.0.30729"的文件,发现了四个.h头文件和一些manifest后缀的文件。
其中我的crtassem.h文件和别人的不同,我的文件中的内容是"9.0.30729.4148",别人的是"9.0.30729.1"。
为什么头文件会不同?那肯定是开发工具补丁包不同了。
通过检查这个头文件的更新时间(2009年8月),再比对开发工具补丁的发布时间以及大家安装的补丁内容,发现我比别人多装了一个补丁:
Microsoft Visual Studio 2008 Service Pack 1 Update (KB974479)
http://www.microsoft.com/en-us/download/details.aspx?id=5687
VS90SP1-KB974479-x86.exe 版本:9.0 (9/8/2009)


如果大家都应用了新的开发工具补丁,版本发布部署是否会有影响呢?部署后是否还会出现用户无法启动的问题呢?
我编译出的版本对"Microsoft.VC90.CRT"库版本要求是version="9.0.30729.4148",而在我机器上实际引用的是"9.0.30729.6161"。
如果发布我出的版本,要发布4148还是6161呢?如果发布6161要怎么处理呢?

看这里:
https://msdn.microsoft.com/zh-cn/library/ms235291(v=vs.90).aspx
“将 Visual C++ 库 DLL 部署为私有程序集”

 

以下因为只是根据目前的VC++ 2008部署经验整理的思路,特别是采用最新版本发布包的做法还未经验证,实施者须自负风险。

为提高兼容性避免部分机器无法启动程序,部署应用程序时VC运行库要部署三处:
1. 在目标机器安装对应开发工具的最新版本redistributable package;
例如对于VC++ 2008 SP1开发的应用,应该建议客户安装:
Microsoft Visual C++ 2008 Service Pack 1 Redistributable Package MFC Security Update (KB2538243)
http://www.microsoft.com/en-us/download/details.aspx?id=26368
版本:9.0 (6/7/2011) (可能有新的版本,但是我在Microsoft官网上找到的最新版本暂时只是这个了)
如果部署的是32位应用程序,要安装vcredist_x86.exe;64位应用程序要安装vcredist_x64.exe。
采用32位还是64位发布包,这和目标机器的操作系统无关,只和要部署的程序是32位还是64位有关,两个包各管各的。
2. 要在应用程序可执行文件所在目录部署它引用到的VC库文件;
具体哪些库需要部署,可以用Dependency Walker检查;
3.
要在应用程序可执行文件目录下建立Microsoft.VC90.CRT和Microsoft.VC90.MFC两个目录并部署相应manifest和dll文件;
3a. manifest文件中描述的库文件版本号应该要和可执行文件manifest要求的一致;
3b. dll文件可以考虑用最新版本的,即实际版本号可以比manifest描述的版本更高;
3c. manifest文件中描述的库文件的其他信息(例如hash值等)应该和实际发布的dll一致;
4. 服务器端运行环境严格受控,只做第一步一般就可以了。

版权声明:本文为博主原创文章,未经博主允许不得转载。

  相关解决方案