`

manifest

 
阅读更多

我遇到的问题:

Upload.exe
Upload.exe.manifest
Microsoft.VC80.CRT.manifest
msvcp80.dll
msvcr80.dll
放在同一目录;
Upload.exe依赖msvcp80.dll和msvcr80.dll,Microsoft.VC80.CRT.manifest里描述的版本version="8.0.50727.762"和系统的版本不同导致运行库异常

转载内容:
一转载:Manifest用途 (2013-02-28 10:18:58)转载▼


关于让自己的程序界面实现XP风格这个问题,在网上的讨论很多,大多数的作法都是写一个.manifest文件,然后将文件名改一下,比如.exe文件为test.exe,就将这个.manifest文件改名成test.exe.manifest,并将其和test.exe放在同一个目录里,这样test.exe在XP或2003(必须启动Themes服务)下运行时就会呈现XP界面风格。那么这个方法为什么有效和怎么将manifest内嵌到exe呢?下面是从网络收集到的一些资料:
1、manifest的原理与用途
        dll是被动态调用的,所以会被若干个程序共享使用的 但是如果dll在应用程序不知道的情况下升级了、或是被另一个程序更改了,就可能会出现问题,即”DLL Hell”。
        随着系统资源越来越丰富,硬盘不那么紧张,所以在XP以后的操作系统中,用新的机制来管理DLL(这种机制,这不仅仅是对于.NET而言,对于普通的Native程序也是一样的)。这种新的机制就是使用manifest文件。
        Manifest是个XML的描述文件,对于每个DLL有DLL的Manifest文件,对于每个应用程序Application也有自己的Manifest。对于应用程序而言,Manifest可以是一个和exe文件同一目录下的.manifest文件,也可以是作为一个资源嵌入在exe文件内部的(Embed Manifest)。
        XP以前版本的windows,会像以前那样执行这个exe文件,寻找相应的dll,没有分别。Manifest只是个多余的文件或资源,dll文件会直接到system32的目录下查找,并且调用。而XP以后的操作系统,则会首先读取Manifest,获得exe文件需要调用的DLL列表(此时获得的,并不直接是DLL文件的本身的位置,而是DLL的manifest)操作系统再根据DLL的Manifest去寻找对应的DLL<因此就可能区别不同版本的同一个DLL文件,或是指定一个程序本身Isolated的DLL>
        不过使用Visual Studio 2005以后的一个新问题是,VS2005带的8.0新版的C运行库(VC 8.0 CRT)文件在XP以后支持manifest的Windows版本中被调用时,将会check一下Application自身的Manifest,否则将会拒绝被调用这也就是说,使用Visual Studio开发的Application,Manifest将是必不可少的(搞不懂MS为啥要这样设置,所以与VS2003.NET不同了)(后来想想,除了MS自己说的哪些冠冕堂皇的原因,至少这样一来Linux的Wine模拟要麻烦多了)
        除非,你的程序是静态链接的,没有使用dll,只使用了操作系统核心的 Kernel32.dll, User32.dll, Ole32.dll, 或ShDocVW.dll 等project的设置必须是Use Standard Windows Libraries、Not Using ATL、No Common Language Runtime support那么你可以不需要考虑Manifest 可以关掉它。
2、使用manifest文件
        本节只讲述VC6.0如何使用manifest文件,关于VS2005或之后的版本,大家可以在网上搜索。
        1)先写一个.manifest文件,比如命名为XPStyle.manifest。直接使用记事本或者其他文本编辑工具即可。文件内容如下:


                         name="XP style manifest"
                 processorArchitecture="x86"
                 version="1.0.0.0"
                 type="win32"/>
  
                
                                                            type="win32"
                                  name="Microsoft.Windows.Common-Controls"
                                  version="6.0.0.0"
                                  processorArchitecture="x86"
                                  publicKeyToken="6595b64144ccf1df"
                                  language="*"
                           />
                
  
        2)使用manifest文件有两种方法
        方法一:将其重命名为程序.manifest,并将其放在程序目录。比如程序名为test.exe,则manifest命名为test.exe.manifest,并将其和test.exe放在同一个目录里,这样test.exe在XP或2003(必须启动Themes服务)下运行时就会呈现XP界面风格。
        方法二:将manifest文件放到资源文件,编译链接后就合进了exe文件。不需要像方法一一样,需要在exe文件旁边放一个manifest。方法二实现方法如下:
        把XPStyle.manifest复制到工程所在目录,再用记事本或其它文本编辑工具手动修改工程目录下的资源文件(.rc),在文件最后加上一行:  
        1 24 “XPStyle.manifest”  
        在VC中编译并连接工程生成.exe可执行文件,运行一下看看。
        就这么简单?就这么简单。
        这里我再多解释一下,最后加上的那一行,“1”代表资源ID,必须是“1”。“24”代表资源类型,我想我们对RT_ACCELERATOR、RT_BITMAP、RT_MENU、RT_STRING等资源都非常熟悉,而“24”实际上是RT_MANIFEST。最后面引号中的东西我就不再啰嗦了。
        好了,编译后的这个.exe文件拿到哪都可以,都是XP风格的界面,不用再依赖.manifest文件了。哦,当然了,必须在XP或2003系统下才可以。
  
        最后有件事情必须说一下,按照上面的方法,test.exe必须先调用InitCommonControls函数(已经废除,不建议使用)或者InitCommonControlsEx函数从comctl32.dll中注册组件类。这一步在VB中是必须的,但是在VC(MFC程序)中,我们好像并没有调用这个函数,可是编译后的程序为什么还能实现XP风格呢?原因是MFC替我们做了这件事。如果我们是让MFC注册的窗口类,它会调用_AfxInitCommonControls函数,而_AfxInitCommonControls的主要操作就是把comctl32.dll装载进来,然后判断.dll文件中有没有InitCommonControlsEx函数,如果有就调用,没有则调用InitCommonControls,到此真相大白。可能有人和我一样,看着以“afx”开头的窗口类名称很不舒服,于是喜欢自己注册窗口类,但在我们注册自己的窗口类时一定要确保调用过InitCommonControlsEx函数,这点一定要记得,如果忘记的话你将会看到一个空白的窗口


二转载:
Microsoft Visual C++ 2008 发布程序的部署问题 2009-08-20 13:07:48
分类:

Microsoft Visual C++ 2008 发布程序的部署问题

这个问题有好多Blog和Forum已经讨论过了,但都不详尽,在具体的操作过程中还是有许多疑问。我摘录并整合了许多网络文章,希望能够做个最终了结。

一、VC2005和VC2008编译出来的程序如何发布
http://www.cppblog.com/lf426/archive/2008/04/12/46885.aspx

VC2005和VC2008编译出来的程序放到别人的电脑上为什么有可能无法运行呢?
1:Microsoft Visual C++ 2008 Express Edition可以发布软件吗?
        能!
        很多人说,因为是Express版,不是Studio,所以只是用来练习语言的,不能发布软件——错!
        除了没有MFC和ATL,基本上跟 .net 版本是一样的。发布出来的,是完整的可执行文件。

2:VC 2008 (2005) 发布出来的程序必须附带上他们特定的dll文件吗?
        不一定。
        如果目标系统是个经常升级的系统,微软已经为其打上了所需要的dll文件补丁了,不需要在软件包里面附加特定的dll文件。特别在Vista系统中,你更是不需要VC8和VC9的dll文件。但是在一些老版本的系统中,这些文件就是必须的。

3:VC2008和VC2005特定的dll文件是哪些?

VC8: msvcm80.dll, msvcp80.dll, msvcr80.dll
VC9: msvcm90.dll, msvcp90.dll, msvcr90.dll

4:如何部署文件?

首先,请选择release版本;在生成可执行文件(exe文件)的时候,会得到相应的部署文件(manifest文件)。比如,得到a.exe文件,就会同时生成a.exe.intermediate.manifest文件。请将这2个文件放在同一文件夹下。然后,你需要VC8和VC9的部署文件:Microsoft.VC80.CRT.manifest和Microsoft.VC90.CRT.manifest。请到你的VC安装目录下寻找,比如:
C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT
我这里也把2个部署文件直接贴出来,没装的直接用就是了:
Microsoft.VC80.CRT.manifest

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<noInheritable></noInheritable>
<assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.762" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
<file name="msvcr80.dll" /> <file name="msvcp80.dll" /> <file name="msvcm80.dll" />
</assembly>

Microsoft.VC90.CRT.manifest

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright (c) Microsoft Corporation. All rights reserved. -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <noInheritable/>
    <assemblyIdentity
        type="win32"
        name="Microsoft.VC90.CRT"
        version="9.0.21022.8"
        processorArchitecture="x86"
        publicKeyToken="1fc8b3b9a1e18e3b"
    />
    <file name="msvcr90.dll" /> <file name="msvcp90.dll" /> <file name="msvcm90.dll" />
</assembly>

然后将VC8的3个dll以及这个manifest装到一个文件夹里,并将文件夹命名为Microsoft.VC80.CRT。
同样将VC9的3个dll以及这个manifest装到一个文件夹里,并将文件夹命名为Microsoft.VC90.CRT。
将这2个文件夹放到与exe文件(及其部署文件)所在目录下就OK了。

二、“应用程序配置不正确,程序无法启动”的原因
http://hi.baidu.com/fairysky/blog/item/130dda13db7b050a5aaf53be.html

vc2005/vc2008采用了新的程序部署技术(manifest清单文件),manifest清单文件实际上类似于我们常用的makefile文件,它定义了程序运行的依赖关系(程序运行所需要的dll库的名称、版本等)。
程序运行,首先根据manifest清单文件(这个文件可以嵌入到exe或dll中,或者单独生成外部文件,可以通过vc2005/vc2008的编译选项控制:工程“属性”->“配置属性”->“清单工具”->“输入输出”->“嵌入清单文件”,选择“是”或“否”来控制)来查找程序运行需要的dll库的名称、版本等,如果所在的系统中没有程序运行所需要的dll库和相应的manifest清单文件,则弹出“应用程序配置不正确,程序无法启动”对话框。
另外要注意,由于vc2005/vc2008与.net集成,导致出现一个新的概念:在.net中,将exe、dll都看成“程序集(assemble)”,每个程序集(assemble)都附带有一个manifest清单文件,因此使得vc2005/vc2008的CRT(C 运行时库)、MFC、ATL等dll库都附带有一个manifest清单文件。
归根结底是由于老版本的系统没有我们开发的程序运行所需要的基本运行时库(2k、xp系统只有vc6的一些dll库,而没有vc2005、vc2008所需要的dll库以及相应的manifest清单文件,而在vista系统或者即将到来的windows 7系统上则包含有vc2005、vc2008的dll库和manifest清单文件)

举个例子:(在XP SP3系统下)

使用vc2008 express sp1版(没有mfc、atl),新建一个“HelloWorld”的“win32控制台应用程序”工程,在release下编译,此时默认的编译选项:(在这里我们只关注与我们的问题相关的几个选项)

1、工程“属性”->“配置属性”->“c/c++”->“代码生成”->“运行库”

默认选项为/MD(release)、/MDd(debug),对这几个编译选项不清楚的可以参见: VC运行库版本不同导致链接.LIB静态库时发生重复定义问题的一个案例分析和总结

2、工程“属性”->“配置属性”->“清单工具”->“输入输出”->“嵌入清单文件”

默认选项为“是”(表示将manifest清单文件嵌入到程序中);当然,我们也可以选择“否”,从而单独生成一个manifest清单文件,不过这会增加不必要的依赖项,因此不建议选择“否”。

编译->链接之后在“ HelloWorld ”工程的release或debug目录下,我们能够看到一个HelloWorld.exe.intermediate.manifest清单文件(根据编译选项,见上,vc2008将manifest清单文件嵌入到了exe程序中,HelloWorld.exe.intermediate.manifest清单文件是一个临时文件,但它的内容与嵌入到exe程序的manifest文件是一样的),用文本编辑器打开该文件(用“记事本”也行,不过格式太乱,看不清楚内容,推荐使用vim或其它的文本编辑器查看),大致内容如下:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
     <security>
       <requestedPrivileges>
         <requestedExecutionLevel level='asInvoker' uiAccess='false' />
       </requestedPrivileges>
     </security>
</trustInfo>
<dependency>
     <dependentAssembly>
       <assemblyIdentity type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
     </dependentAssembly>
</dependency>
</assembly>

我们重点查看红色部分,这说明编译后的exe程序依赖于vc90(也即vc2008)的CRT(C运行时库),版本9.0.210022.8(这是由于使用/MD选项,程序动态的依赖于CRT,如果使用/MT选项,则会将CRT静态链接到程序中,当然,这会使程序的尺寸急剧的增长,大概有10倍的大小差距)

当exe程序执行时,它会根据嵌入的manifest文件查找相应的依赖项,在这个HelloWorld.exe程序中,它依赖于vc90 CRT,因此它会在“C:\WINDOWS\WinSxS”和“当前目录”下查找相应的dll库以及manifest文件,(这里指的是xp系统,不考虑vista系统,具体的参见:程序集搜索顺序)

在我的机器上有2个版本的vc90 CRT(由于安装了vc2008 express sp1)

vc90 CRT的dll库位于(9.0.21022.8版本)“C:\WINDOWS\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375”

相应的manifest文件则位于“C:\WINDOWS\WinSxS\Manifests\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_d08d0375.manifest”

vc90 CRT的dll库位于(9.0.30729版本)“C:\WINDOWS\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e”

相应的manifest文件则位于“C:\WINDOWS\WinSxS\Manifests\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e.manifest”

在这里我们就有一个疑问了,我们的开发环境是vc2008 express sp1,那么我们的程序链接的CRT版本应该是9.0.30729版本的啊?(这个不是我瞎说的,大家可以用dependency walker来查看程序实际链接的DLL版本),为什么在manifest文件中依赖的CRT却是9.0.21022.8版本的? 这里就涉及到一个新的名词“policy ",操作系统会根据C:\WINDOWS\WinSxS\Policies \x86_policy.9.0.Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_x-ww_b7353f75 \9.0.30729.1.policy文件的内容,进行dll版本的跳转(重点看深蓝斜体字部分)从而选择了9.0.30729版本的vc90 CRT (这个所谓的“policy跳转”是道听途说来的,具体的英文资料藏在microsoft的什么地方我就不得而知了。里面夹带了一些我自己的主观猜测,不然的话,没有办法解释manifest版本号9.0.21022.8是,而实际链接的dll的版本号却是9.0.30729)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright (c) Microsoft Corporation. All rights reserved. -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity type="win32-policy" name="policy.9.0.Microsoft.VC90.CRT" version="9.0.30729.1" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
    <dependency>
        <dependentAssembly>
            <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
            <bindingRedirect oldVersion="9.0.20718.0-9.0.21022.8" newVersion="9.0.30729.1"/>
            <bindingRedirect oldVersion="9.0.30201.0-9.0.30729.1" newVersion="9.0.30729.1"/>
        </dependentAssembly>
    </dependency>
</assembly>
如果我们将这个HelloWorld.exe拷贝到其它的机器上(没有安装vc2008 sp1或Microsoft Visual C++ 2008 SP1 Redistributable Package (x86)),则程序因为没能找到vc90 CRT,而不能运行,弹出“应用程序配置不正确,程序无法启动”对话框。

根据参考资料的文章中的内容,对于release版程序,有一个简单的办法就是安装“vcredist_x86.exe”,文件大小4M左右,自动安装在“C:\WINDOWS\WinSxS”目录下,包含了CRT、MFC、ATL等库的dll和manifest清单文件;整个安装时间不到1分钟。

如果机器上安装了vc2005/vc2008,则会自动的安装vcredist_x86.exe程序,安装后在“控制面板”->“添加删除程序”中有一项“Microsoft Visual c++ 2008 Redistributable - x86 9.0.3.729”(我安装的是Microsoft Visual C++ 2008 SP1 Redistributable Package (x86) 版本)

注意:要根据编译器版本以及vc2005/vc2008是否安装了sp1补丁进行选择对应的vcredist.exe版本

上述的解决办法我称之为共享程序集部署方法,同样的我们也可以采用私有程序集的部署方式来发布程序。

Helloworld例子的私有程序集的部署方法:(针对release版本,仍然是采用上面的例子

,采用参考资料中提到的第2中私有程序集部署方法:将Microsoft.VC90.CRT目录下的manifest文件的版本号修改为9.0.21022.8)

1、将编译后的程序拷贝到一个目录下,假定为d:\helloworld

2、将vc安装目录下的redist\x86目录下的Microsoft.VC90.CRT目录拷贝到d:\helloworld(假定vs安装在C:\Program Files\Microsoft Visual Studio 9.0,则vc安装目录为C:\Program Files\Microsoft Visual Studio 9.0\VC)

3、将Microsoft.VC90.CRT目录下的manifest文件的版本号修改为9.0.21022.8(用记事本打开修改)

最终发布程序的目录结构

D:\helloworld

      |--helloworld.exe

      |--Microsoft.VC90.CRT

                     |--Microsoft.VC90.CRT.manifest

                    |--msvcm90.dll

                     |--msvcp90.dll

                    |--msvcr90.dll

这个时候,程序的manifest文件(已经内嵌到exe中了)依赖的vc90 CRT的版本号和Microsoft.VC90.CRT.manifest文件的版本号对应一致,都是9.0.21022.8(但是要注意的是,我们的helloworld程序实际上依赖的vc90 CRT版本是9.0.30729版本,这里只是采用了一种欺骗的方法,因为我们编译时链接的CRT的版本是9.0.30729版本)

三、发生二个DLL版本错乱的原因

http://blogs.msdn.com/vcblog/archive/2008/05/15/vc-runtime-binding.aspx
Virtual C++ 2008提供一个选项,可以选择使用那个版本的DLL,是9.0.21022.8还是9.0.30729.1
1. 9.0.21022.8也称RTM版本
2. 9.0.30729.1也称Current当前版本
VC提供ploicy DLL版本策略转发功能,可以将老版本的DLL请求转发到新版本上,这意味着
1. 使用RTM版本的库可以被指向RTM版本或更高版本
2. 使用当前版本的库可以被指向当前版本或以后新出的版本

对于下面情况,一般使用RTM版本的库
alan使用RTM版本的产品,并发布给客户
MS释放出VS SP1, 客户安装并使用了新版本的库
alan发现他的产品有问题,修复并将其再次发给客户
在这种情况下,alan不知道客户使用的是那个版本的库,他发布的产品使用RTM版本的库,如果有策略转发,则使用新版本的库

另外一种情况
jim使用RTM版本的库开发
jim发现RTM版本库中有bug,并将其提交给MS
MS修复,并发布新版本库
jim使用新版本库,工作正常。
jim的产品是否正常依赖于是否使用新版本的库,如果不能正常使用,还不如不让程序运行
因此我们提供多个版本库,并向后兼容。

四、人工指定使用那个版本的库
在编译时,使用编译选项
1. MFC使用 _BIND_TO_CURRENT_MFC_VERSION=1
见afx.h
2. CRT使用 _BIND_TO_CURRENT_CRT_VERSION=1
见 crtdefs.h 和 crtassem.h
总共有如下的设置
#define _BIND_TO_CURRENT_CRT_VERSION 1
#define _BIND_TO_CURRENT_ATL_VERSION 1
#define _BIND_TO_CURRENT_MFC_VERSION 1
#define _BIND_TO_CURRENT_OPENMP_VERSION 1
其实,我们可以用_BIND_TO_CURRENT_VCLIBS_VERSION=1 来代替以上四项。
但这个参数在可能会有问题
五、链接多种库的情况
http://www.codeguru.com/cpp/v-s/devstudio_macros/visualstudionet/print.php/c15611
在现实中,一个应用程序需要链接多个库,这要求所有的库都使用同样版本的VC DLL,否则会这样

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.30729.1" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>


应用程序即依赖于9.0.30729.1的DLL,还依赖于9.0.21022.8版本的
如何判断库函数的版本呢,使用VC自带的dumpbin
dumpbin /directives <name>.lib
会输出如下信息,
/manifestdependency:"type='win32'
name='Microsoft.VC90.CRT'
version='9.0.30729.1'
processorArchitecture='x86'
publicKeyToken='1fc8b3b9a1e18e3b'"
/manifestdependency:"type='win32'
综述,请确保应用程序,所有库函数都使用相同版本的VC DLL



比较潦草,从不同的地方整理而来。不明白请看原文

转载三:
害人的VS2008,manifest导致“应用程序配置不正确,应用程序未能启动”
在VC++2008的项目中,如何显示地指定要使用的C++库的版本?

开发环境:VS2008 SP1 + Win2003 SP2
        因为我的VS2008安装了SP1补丁,所以有了9.0.30729.1的MFC库文件(MFC90.DLL MSVCR90.DLL)。


新建了一个MFC应用程序,编译为RELEASE版本,叫做“test1.exe”,可以从程序中的清单文件(manifest)看到以下内容:
XML code
...   <dependency>         
        <dependentAssembly>

            <assemblyIdentity type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b'/>

      </dependentAssembly>

     </dependency>

     <dependency>

        <dependentAssembly>

            <assemblyIdentity type='win32' name='Microsoft.VC90.MFC' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b'/>

        </dependentAssembly>

     </dependency> ...




说明本程序需要引用版本号为9.0.21022.8的MFC库和运行时库。

问题一:为什么程序在运行的时候,载入的不是9.0.21022.8版本的却是9.0.30729.1版本的运行库?这是在哪里进行设置的?如何改变这个版本号?

问题二:(虽然貌似已经解决,但是我想知道的更深一点)
布署的时候,把X:\VS安装目录\VC\redist下对应的运行库和.manifest文件(都是9.0.30729.1版本的)复制到与test1.exe同一目录下。在一台完全干净的新系统中,会出现“应用程序配置不正确,应用程序未能启动”的错误。

后来,经过不断的试验,发现应用程序中的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 --> 可以运行

注:运行库MANIFEST文件是指Microsoft.VC90.CRT.manifest和Microsoft.VC90.MFC.manifest,运行库DLL是指MSVCR90.DLL MFC90.DLL

程序的清单文件不要内嵌,而使用外置的MANIFEST文件,然后手工把生成的text1.exe.manifest中的version='9.0.21022.8'改成新版本号version='9.0.30729.1' ,就可以达到以下目标了:
应用程序 外置的MANIFEST文件[使用了使用了新版本DLL的功能 却指定了新的版本号] + 新版本的运行库MANIFEST文件 + 新版本的运行库DLL --> 可以运行!
(内嵌清单也是资源,当然可以修改,但是不建议这么做,而且也没必要这么做。)

终于终于,在微软网站找到了关于这个问题的描述。
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=361682
这的确是个BUG,具体什么时候会修复就不知道了。。。。。。。。

所以,内嵌清单中的版本号只能为旧版本号,因此目前只能用,旧版本的运行库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)链接器-->清单文件-->生成清单:是

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics