将VC6.0的Dll移植到VS2008时,写了一个Test.exe程序加载Dll,LoadLibrary时出现“找不到mfc90u.dll”的提示。由于是新安装的VS2008,所以在安装目录“C:\Program Files (x86)\Microsoft VisualStudio 9.0\VC\redist\amd64”下是找得到这些Dll的,且版本为'9.0.21022.8'。查了一下,有可能是Manifest文件的问题。
vc2005/vc2008采用了新的程序部署技术(manifest清单文件),manifest清单文件实际上类似于我们常用的makefile文件,它定义了程序运行的依赖关系(程序运行所需要的dll库的名称、版本等)。
程序运行,首先根据manifest清单文件(这个文件可以嵌入到exe或dll中,或者单独生成外部文件,可以通过vc2005/vc2008的编译选项控制:工程“属性”->“配置属性”->“清单工具”->“输入输出”->“嵌入清单文件”,选择“是”或“否”来控制)来查找程序运行需要的dll库的名称、版本等,如果所在的系统中没有程序运行所需要的dll库和相应的manifest清单文件,则弹出“应用程序配置不正确,程序无法启动”对话框。
用记事本打开这个要移植的这个Dll(Net.dll),发现底下并没有配置文件信息,说明这个Dll的配置文件并不是内置的,而是读的外部的.manifest文件。问题就出在这里。由于是从VC6移植过来的,因此读的这个.Manifest文件中的配置信息并不是本地电脑上的运行时库Dll的版本,因此会出错。
注:运行库MANIFEST文件是指Microsoft.VC90.CRT.manifest和Microsoft.VC90.MFC.manifest,运行库DLL是指MSVCR90.DLLMFC90.DL
网上有资料显示:
应用程序中的MANIFEST文件指定的是9.0.21022.8版本的运行库,然后我使用9.0.21022.8版本的Microsoft.VC90.CRT.manifest文件替换9.0.30729.1版本的Microsoft.VC90.CRT.manifest,配合上30729版本的MFC90.DLL,程序就可以正常运行了。
简单一点,就是,对于一个使用了
新版本DLL功能的应用程序,有以下情况:
应用程序中的MANIFEST文件[使用了使用了新版本DLL的功能却指定了旧的版本号] + 新版本的运行库MANIFEST文件 + 新版本的运行库DLL --> 不可以运行
应用程序中的MANIFEST文件[使用了使用了新版本DLL的功能却指定了旧的版本号] + 旧版本的运行库MANIFEST文件 + 旧版本的运行库DLL --> 不可以运行
应用程序中的MANIFEST文件[使用了使用了新版本DLL的功能却指定了旧的版本号] + 旧版本的运行库MANIFEST文件 + 新版本的运行库DLL --> 可以运行
最后,解决的办法就是重新创建一个项目,并且选择内置清单文件。这样,配置文件中的运行时库版本就和本地电脑上的一样了。
设置方法:
在VS2008中,“项目”-->“属性”-->“配置属性”-->“清单工具”-->“输入和输出”-->“嵌入清单”-->否。
这样程序编译后,假设是mytest.exe,将会产生一个mytest.exe.manifest,发布软件时最好附带上这个manifest文件,用记事本打开,可以看到对应MFC/CRT.manifest的版本。
在VS2008中,“项目”-->“属性”-->“配置属性”-->“清单工具”-->“输入和输出”-->“嵌入清单”-->是。mytest.exe将包含mytest.exe.manifest,不额外产生mytest.exe.manifest。
“配置属性”其它设置:(1)常规-->MFC的使用:在共享DLL中使用MFC;(2)C/C++ -->检查64位可一致性问题:否;(3)C/C++ -->代码生成-->运行时库:多线程调试DLL(/MDd);(4)链接器-->清单文件-->生成清单:是
最后,用记事本打开生成的Dll文件,就出现一下的配置信息了: