DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

用VS2008 SP编写的MFC程序,拷贝到其他没装VS2008的机器上直接运行,肯定是不行的。即使选择静态链接MFC,有时候系统还是会提示“应用程序配置不正确”。这是因为程序中可能不止用到了9.0版本MFC,还可能有ATL、CRT、OPENMP等。在自己的机器上运行时,系统会到"C:/WINDOWS/WinSxS/"文件夹查找相应的库,这个文件夹里包含了所有安装过的版本的运行库和清单文件。如果只找9.0版本的库和清单文件,也可以到"C:/Program Files/Microsoft Visual Studio 9.0/VC/redist/x86"这个文件夹。

 

对于只用到Release库程序:

拷贝需要的库和清单文件到exe所在目录,修改程序的清单文件,再移植就可以运行了。修改的方法是:用Release方式编译链接程序,然后修改xxx.exe.intermediate.manifest,将其中name为Microsoft.VC90.CRT、Microsoft.VC90.MFC等的dependency块删掉,生成(不是重新生成!)项目,VS会把清单文件重新嵌入到程序中。这样,到了目标机器上,系统就不会按照清单文件到WinSxS文件夹去查找库(当它找不到时,就会提示“配置错误”。从“事件查看器”中,会看到加载失败的信息),而是到了该加载时才从工作目录查找。网上很多说法都提到了拷贝dll和manifest,但如果不修改程序中嵌入的manifest的话,拷贝了也是没用的。

 

另外一个不需要修改清单文件的办法,是下载Microsoft Visual C++ 2008 Redistributable Package,只有几兆,到目标机器上安装就可以了。这是vcredist_x86 for VS2008 的下载地址:

http://www.microsoft.com/downloads/details.aspx?FamilyID=9b2da534-3e03-4391-8a4d-074b9f2bc1bf&displaylang=en

这是vcredist_x86 for VS2008 SP1的下载地址:

http://www.microsoft.com/downloads/details.aspx?familyid=A5C84275-3B97-4AB7-A40D-3802B2AF5FC2&displaylang=en

两个安装程序的版本略有差别。

 

当然,如果只用到了9.0版的MFC,只要选择“在静态库中使用MFC”,就可以运行了。

 

 

对于用到Debug库程序:

如果你的程序用到了Debug版的运行库,那么上述库是不能解决问题的,因为它们都是Release版。可以到"C:/WINDOWS/WinSxS/",把用到的文件夹拷贝到目标机器的WinSxS中。不过我用的仍是修改清单文件的办法:从"C:/Program Files/Microsoft Visual Studio 9.0/VC/redist/Debug_NonRedist/x86"文件夹中,把用到的dll和MANIFEST拷贝到exe所在目录。用Release版编译链接程序(我的程序用到了OpenCV2.0的Debug库,而该库似乎用到了DebugCRT和DebugOpenMP。因此我的程序同时用到了Debug和Release的C Runtime),然后修改xxx.exe.intermediate.manifest,将其中的DebugCRT项目删掉,生成(不是重新生成!)项目,VS会把清单文件重新嵌入到程序中,完成!

 

还可以在“项目属性-清单工具-输入和输出”中将“嵌入清单”置为否,这样清单就不会被嵌入到exe中,而是被输出到了exe所在的文件夹。打开该清单文件,将Debug库删掉,最后将exe和清单文件一起拷贝到其他计算机。

 

另外,如果新建一个“安装项目”,在项目上点右键-添加-合并模块,似乎可以选择一些需要的库打包进安装文件中。安装时,这些被选上的库会被复制到WinSxS文件夹。一切看上去都没什么问题,唯一的问题是——我这样尝试后,发现仍是“初始化失败”

 

 

 

总结一下吧,想要移植一个程序,首先要知道这个程序依赖那些系统库,这一点可以查看它加载了哪些模块;其次要让程序知道,在新的计算机中,是到WinSxS文件夹寻找,还是到程序所在文件夹寻找,可以通过修改清单文件做到这一点。

 

更新:10.11.29

刚刚搞定了一个opencv的dll的问题。Release版本的cvCvtColor函数总是出错,发现原来是我编译的有问题,从网上下dll就好了。从而也不用再用debug版本的dll了。下面开始解决可移植性的问题。

项目属性-链接器-清单文件:生成清单:是;

        -清单工具-输入和输出:嵌入清单:否。

在生成的xx.exe.manifest文件中,可以看到CRT和MFC(如果没有静态编译MFC)的版本,比如我的版本是9.0.21022.8。似乎调用时如果机器上安装了更高的小版本,就会去调用小版本。

打开VS2008的安装目录/VC/redist/x86(我之前用winsxs中的文件,但不能运行。),找到其中对应版本的dll和manifest,拷到程序文件夹。如果没有对应版本,更高的小版本似乎也可以,不过此时就需要修改xx.exe.manifest使版本号相同。

拷贝到新机器,也不用安vcredist,运行:成功!

 

再更新:

vcredist还是要安的。我查看进程,发现拷贝过去的crt+mfc dll和winsxs中的dll都被调用了,原因未知。

 

参考资料:

http://topic.csdn.net/u/20080825/00/8bccaafe-0006-4052-92b4-c99cb71c232f.html 

posted on 2013-01-21 14:51  DoubleLi  阅读(2650)  评论(0编辑  收藏  举报