问题表现
遇到了这么一个问题:用VC++2005开发的程序P,到了别的机器上却不能运行,提示“由于应用程序配置不正确,程序未能启动”。
原因分析
可能是缺乏C++ Runtime或C++ Runtime版本不正确引起。虽然都是VC8.0,开发机上跟踪程序线程,发现程序P调用了:
C:\WINDOWS\WinSxS\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.4053_x-ww_e6967989\MSVCR80.dll。
dll版本是8.0.50727.4053,而运行机是8.0.50727.762。
解决
到微软下载VC++2005运行时可再发行包,安装后,运行机就可以运行程序P了。
http://www.microsoft.com/downloads/details.aspx?FamilyID=766a6af7-ec73-40ff-b072-9112bab119c2&DisplayLang=zh-cn
另一种思路
考虑到用户体验,没人愿意在使用程序P之前进行额外的安装操作,打算采用另一种思路:把所需的dll全部拷贝到程序P的运行目录下。于是将MSVCR80.dll拷贝到运行目录下,再执行程序P,奇怪的是问题并没有得到解决,同样提示“由于应用程序配置不正确,程序未能启动”。
google后发现这种dll明明存在却找不到的现象是由一个名为manifest的文件引起的。微软为了解决dll地狱,从xp系统开始就引入了扩展名为manifest的文件,也就是清单文件。该类型的文件的内容是一段xml,描述了程序运行依赖的dll版本。程序调用dll时,首先找dll的manifest文件,之后再找到符合manifest描述的dll。当程序P想调用msvcp80.dll时,并没有找到相关的manifest文件,因此就提示了应用程序配置不正确。
我们到开发机VS安装目录Microsoft Visual Studio 8\VC\redist\x86下找到文件夹Microsoft.VC80.CRT,该文件夹内存放着三个VC++ 8.0 Runtime的dll文件和一个manifest文件,将这个manifest文件拷贝到程序P的运行目录下。再次执行程序P,成功。
另一种思路的解决
到开发机VS安装目录Microsoft Visual Studio 8\VC\redist\x86下找到文件夹Microsoft.VC80.CRT,将文件夹内的所有文件(三个dll,一个manifest)全部拷贝到程序P的运行目录内。
如果想运行目录整洁一些,也可直接将Microsoft.VC80.CRT文件夹拷贝。
注意:
1、文件夹名称只能是“Micorsoft.VC80.CRT”,不能改成其他,如“lib ”、“dll”;
2、清单文件的名称不能改,只能是“Micorsoft.VC80.CRT.Manifest” ;
3、清单文件必须和dll在同一目录。
回顾
再回到本文最初,可以领悟到当初的错误提示它的真正含义是“我没有找到所需dll的manifest文件”,而不是“我没有找到所需的dll文件”。
这一点也可以通过分析安装VC++2005运行时可再发行包前后系统目录C:\WINDOWS\WinSxS发生的变化得到印证。
安装以后,该目录下会增加一个新目录,名为:x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.4053_x-ww_e6967989,其内放着三个C++ Runtime dll文件:msvcm80.dll,msvcp80.dll,msvcr80.dll;
同时C:\WINDOWS\WinSxS下的manifests文件夹内会增加两个文件:x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.4053_x-ww_e6967989.Manifest,x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.4053_x-ww_e6967989.cat。这里显然微软对自己和对别人采取了双重标准,清单文件和dll文件并没有放在同一目录下。
如果把第一个.Manifest文件删除,再次执行程序P,会发现本文开头的错误提示再一次又出现了。
那么真正的缺少dll文件的提示是怎样的呢?
保留manifest,把dll删除再运行就可以看到:“应用程序正常初始化(0xc0000034)失败”。
补充
Visual Studio 2005 + SP1的VCRT版本:8.0.50727.762。
Visual Studio 2005 + SP1 + VS80sp1-KB937061 + VS80sp1-KB971090 + VS80sp1-KB947738 VCRT版本:8.0.50727.4053。
因为几个安全补丁是同时装的,因此不确定是那个升级了VCRT。可以确定的是微软的安全漏洞真大,一个补丁KB971090就有249M,让我想起了一个乞丐拿扣子请好心人给他补条裤子的故事。