超级总结:vs2008/2005 sp1 C++ 发布程序 .

最近在新装的Win7上 编译/ 运行自己的 camera_work_simultaneously.exe 程序时,发现release 编译/运行 没有问题,但是Debug版本编译通过,run时报错:“The application was unable to start correctly(0x0000006). ....”

 再查看系统的event,

把在笔记本上用VC9.0发布的SCCT.exe文件拷贝到 装有Win7的 台式机BV5上进行验证,也是出同样的问题!就是调用GigEVisionSdkD.dll时依赖的GenApi_MDd_VC80.dll又依赖与Microsoft.VC80.DebugCRT的运行时库,最后没有找到Microsoft.VC80.DebugCRT。

 于是进行下列步骤:

C:\Users\BV5\Desktop\SCCT\Debug  

      |--scct.exe

      |--opencv_calib3d231d.dll

      |--opencv_core231d.dll

                         .                    .

                         .    

      |--GigEVisionSdkD.dll

      |--GenApi_MDd_VC80.dll

      |--GCBase_MDd_VC80.dll

     (Microsoft.VC90.DebugCRT下的dll放到SCCT\下)

       |--Microsoft.VC90.DebugCRT.manifest

       |--msvcm90d.dll

       |--msvcp90d.dll

       |--msvcr90d.dll

       |--GenICam\bin\Win32_i86\GenApi\Generic

                                                                                  |--XMLLoader_MDd_VC80.dll

                                                                                  |--xerces-c_2_7.dll

                                                                                  |--Xalan-C_1_10.dll

                                                                                  |--XalanMessages_1_10.dll

GigEVision的在SCCT\下的目录结构参考 “发布带GigEVision的程序 http://blog.csdn.net/jtop0/article/details/6934210”

1、在Win7上(也就是 Winsxs目录下)没有Microsoft.VC80.DebugCRT 运行时库? (的确

虽然

2、下载到Microsoft.VC80.DebugCRT 库 版本8.0.50727.762, 并分别放到应用程序目录SCCT\下 和 SCCT\GenICam\bin\Win32_i86\GenApi\Generic下(因为running时,启动camera要调用XMLLoader_MDd_VC80.dll,这个dll 又依赖于Microsoft.VC80.DebugCRT库, 当然如果能找到msi文件的Microsoft.VC80.DebugCRT直接安装到Winsxs目录下,就可以共用了,不用再把运行时库拷到SCCT\目录下了

                     .

                     .

     |--GCBase_MDd_VC80.dll

    ( Microsoft.VC90.DebugCRT运行时库 )

      |--Microsoft.VC90.DebugCRT.manifest

      |--msvcm90d.dll

      |--msvcp90d.dll

      |--msvcr90d.dll

    ( Microsoft.VC80.DebugCRT运行时库 )

      |--Microsoft.VC80.DebugCRT.manifest

      |--msvcm80d.dll

      |--msvcp80d.dll

      |--msvcr80d.dll

       |--GenICam\bin\Win32_i86\GenApi\Generic

                                                                                  |--XMLLoader_MDd_VC80.dll

                                                                                  |--xerces-c_2_7.dll

                                                                                  |--Xalan-C_1_10.dll

                                                                                  |--XalanMessages_1_10.dll

                                                                                  |--Microsoft.VC80.DebugCRT.manifest

                                                                                  |--msvcm80d.dll

                                                                                  |--msvcp80d.dll

                                                                                  |--msvcr80d.dll

 

并且修改Microsoft.VC80.DebugCRT.manifest把版本号改为8.0.50608.0GCBase_MDd_VC80.dll、GenApi_MDd_VC80.dll中嵌入的manifest 版本一致

当然Microsoft.VC90.DebugCRT.manifest中的版本号,也应该改为 9.0.21022.8与嵌入scct.exe、GigEVisionSdkD.dll的manifest要求的版本一致

3、把机器上的目录C:\Program Files\MaxxVision\GigEVision改为C:\Program Files\MaxxVision\GigEVision1 以便运行scct.exe时,避免用系统中的GigEVision库,而使用SCCT\目录下的GigEVision库以及GenApi_MDd_VC80.dll、GCBase_MDd_VC80.dll等。

4、再次运行scct.exe程序OK!

 

实际上这个问题根本上还是涉及到  vs2008/2005 sp1 C++ 发布程序的问题!

先参考我的前一篇blogvs2008 sp1 C++ 发布程序

 

现在对这个发布 作一个全方位的总结: 

一、使用vs2008/vs2008开发的程序有2种部署方法:

静态链接发布:只要拥有程序的所有源代码(包括库),你就可以采用静态链接到crt 和 MFC,来发布程序,运行时 只要一个exe文件就可以了,只不文件体积太大了点。

动态链接发布:编译程序时, 采用动态链接 运行时库,即在project property---C/C++---Code Generation---Runtime Library 选 /MDd,发布的exe应用程序还要附带Runtime Library (dll) 程序才能运行(常用的方法)。

                         |-----------并行程序集 部署方法

                         |-----------私有程序集 部署方法

所谓的共享并行程序集部署方法是指程序依赖的CRT、MFC、ATL的DLL和manifest文件位于目标机器上的c:/windows/winsxs目录中,发布程序的时候只需要将程序拷贝到目标机器上就可以了;私有程序集部署方法指的是发布程序程序的时候,将所依赖的crt、mfc、atl的dll放在程序的当前目录下.

 静态链接发布

动态链接发布

               |----并行程序集 法 (3 种方法

                             1 |-----目标机器安装了VS开发环境(vs2005 sp1/vs2008 sp1)则在机器上同时也安装了共享并行程序集,包含各个版本的dll(8.0、9.0版本,位于C:/Windows/Winsxs目录下),则不需做任何的部署,直接将需要发布的程序拷贝到目标机器上就可以了.

                             2 |-----安装vcredist.exe (Microsoft Visual C++ 2008 SP1 Redistributable Package (x86)

                             3 |-----用vs2008 的Redistibutable Merge Modules 去install 特定的VC++库,(即用vs2008新建一个Setup and Deployment 的项目包含exe需要的运行库,当install时就把相关的运行时库自动放到winsxs中去了 )

 

                |----私有程序集法 (1 种方法 2 steps

                              step1|-----拷贝C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\x86目录下的文件夹“Microsoft.VC90.CRT”下的4个文件到 应用程序文件夹下如:SCCT\

                                                                                                                    |--Microsoft.VC90.CRT.manifest

                                                                                                                    |--msvcm90.dll

                                                                                                                    |--msvcp90.dll

                                                                                                                    |--msvcr90.dll

                              step2|-----  并且修改 application.exe 和 Microsoft.VC90.CRT.manifest 中各自的manifest 描述 运行时库版本不一致问题(只在安装了vs2005 sp1/vs2008 sp1后才会出现),(有2类方法)

                                                                 1|--------修改application.exe 中manifest描述的运行时库版本号 9.0.21022.8 与 实际compile 时采用的运行时库版本号(Microsoft.VC90.DebugCRT.manifest中9.0.30729.1)一致.

                                                                                 a|------在编译项目时定义一个符号_BIND_TO_CURRENT_VCLIBS_VERSION,该符号定义于C:/Program Files/Microsoft Visual Studio 9.0/VC/include/crtassem.h 文件中(假设VC安装在c盘),这样使得编译后的程序的manifest依赖于CRT 9.0.30729.1版本

                                                                                b|------(嵌入manifest)通过外部工具修改生成的exe或dll中manifest文件(vc2008 打开application.exe 双击在RT_MANIFEST下的"1" ,或者“记事本”打开application.exe修改版本号 好像windows sdk中的mt.exe也可以做到)

                                                                                c|------(未嵌入manifest)通过“记事本”打开application.exe.manifest文件修改

                                                                  2|---------修改实际compile 时采用的运行时库版本号9.0.30729.1(描述在Microsoft.VC90.CRT.manifest中)为  application.exe 中manifest描述的运行时库版本号9.0.21022.8为号一致 .即:用“记事本”在step1的application.exe所在目录中把Microsoft.VC90.CRT.manifest文件描述的版本号9.0.30729.1改为9.0.21022.8

          以上为Release版本的发布方法。Debug版本的application.exe 发布 上面 |----并行程序集 法 (3种方法)的第2中方法行不通。因为vcredist.exe只安装了release版的CRT、MFC、ATL的DLL和manifest文件,没有对应的debug版本。

          vc2005 sp1 版本号是:  8.0.50727.726      对应的RTM   版本号是:8.0.50608.0  

         

二、 关于 私有程序集 法 的说明:

1、只有在从未安装过Microsoft.VC90.CRT运行时库的机器中(也就是winsxs文件夹下没有相应的Microsoft.VC90.CRT库),私有程序集法才真正起作用,也就是 application.exe文件调用 当前文件夹下(私有发布的)Microsoft.VC90.CRT 运行时库。

2、如果机器中已经安装了Microsoft.VC90.CRT(也就是winsxs文件夹下能找到),则 当运行application.exe时 首先调用 系统的(winsxs文件夹下)Microsoft.VC90.CRT运行时库,不会调用私有的Microsoft.VC90.CRT运行时库。

3、如果系统中安装的Microsoft.VC90.CRT运行时库有错误,则应用程序不能运行,回报错,也不会调用私有的Microsoft.VC90.CRT运行时库。唯一的解决方法就是 重新install 运行时库。

4、要想强制应用程序application.exe调用 当前文件夹下(私有发布的)Microsoft.VC90.CRT 运行时库,而不管系统有无运行时库,要同时去掉application.exe 和

Microsoft.VC90.CRT.manifest 中的“publicKeyToken” 属性,详见How to bypass the WinSxS for CRT/MFC/ATL DLLs:

 

If a DLL is installed in the WinSxS folder, the local DLLs will be ignored. So, if you want to be independed from global DLLs,  a method is :just remove the “publicKeyToken” attribute from the manifests!

So an application manifest looks like:

Application.exe.manifest:

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.42" processorArchitecture="x86" /> </dependentAssembly> </dependency> </assembly>

You must also set the correct verion-number of the DLL! And remove the “publicKeyToken” attribute.
The manifest the for DLL looks like:

Microsoft.VC80.CRT.Manifest:

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.42" processorArchitecture="x86"></assemblyIdentity> <file name="msvcr80.dll"></file> <file name="msvcp80.dll"></file> <file name="msvcm80.dll"></file> </assembly>

Now the CRT DLLs in the WinSxS will be ignored and only the local DLLs will be loaded.

三、side-by-side assembly方法是MS 没有用注册表来进行的运行库控制,

--------仅仅在Windows XP后的版本才有这个特性

-------VC2005和VC2008采用了具有C runtime libraries 的 SxS

-------而VC2010中已经放弃这中方法,而是直接在dll文件后加一个版本号,用同名的dll 只要版本号不同,以后也视为两个dll。 如 msvcr100.v1.dll

要装载Win32本地 的运行时库到winsxs下,只有通过MSI(the Windows Installer)或第三方专用工具如InstallMate 7才可以, .不能手动加入。

 

参考链接:

微软的Dll管理方案及其变迁(Side-by-side assembly)http://www.cnblogs.com/zhihuichien/archive/2011/03/24/1993447.html

关于vc2005的找不到MSVCR80.dll的执行错误http://blog.csdn.net/lionzl/article/details/6015394

关于manifest,这个文章最detailhttp://blog.csdn.net/fuzb/article/details/6730826

How to bypass the WinSxS for CRT/MFC/ATL DLLshttp://blog.kalmbachnet.de/?postid=80

Vista & Windows Side by Side Assemblieshttp://kartones.net/blogs/kartones/archive/2007/05/01/vista-windows-side-by-side-assemblies.aspx

如何:部署“安装和部署项目”http://msdn.microsoft.com/zh-cn/library/ms235317(v=VS.90).aspx

http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/951fad2d-3e0a-4342-96a7-6aa318c90caa/

SxsTrace程序追踪工具介绍及其使用http://www.sunchis.com/html/hsware/software/2010/0821/199.html

Using Windows side-by-side assemblieshttp://www.tarma.com/support/im7/kb/kb50036.htm

你可能感兴趣的:(C++,windows,Microsoft,assembly,dll,mfc)