详解Manifest文件使用

作者: admin 分类: 开发问题 发布时间: 2015-02-11 14:24 ė3,180 浏览数 6没有评论
文章转自王牌软件
站长推荐:NSetup一键部署软件
一键式完成美化安装包制作,自动增量升级,数据统计,数字签名。应对各种复杂场景,脚本模块化拆分,常规复杂的脚本代码,图形化设置。无需专业的研发经验,轻松完成项目部署。(www.nsetup.cn)

在Windows 2000时代,客户端软件A使用1版本的R.DLL,客户端软件B使用2版本的R.DLL。不巧系统上只能够存在一个版本的DLL文件,但是用户需要同时安装了软件A和软件B。这时有两种情况:

  1.  系统安装了2版本的R.dll,软件A错误地使用了2版本的R.dll,软件B正常运行。
  2.  系统安装了1版本的R.dll,软件B错误地使用了1版本的R.dll,软件A正常运行。

上面两种情况都会可能导致致命的错误。针对上面所说的问题,微软从Windows XP后引入了Side-by-Side Assemblies(并行程序集)技术,为了减少Windows客户端程序之间的版本冲突。而应用程序通过Manifest(程序清单)描述并行程序集。

一个并行程序集,可能包括了一系列的DLL,Windows类,接口,COM组件。从Windows XP开始,应用程序能够同时使用多个不同版本的程序集。DLL加载器通过读取Manifest文件的描述决定加载正确版本的程序集。

举例来说,Comctl32.DLL是一个系统DLL,在Windows系统中有两个版本Comctl32.DLL,Comctl32.DLL 6.0版本和Comctl32.DLL 5.0版本,Comctl32.DLL是一个并行程序集。当应用程序需要加载DLL时,Side-by-Side 管理器先判断Manifest是否有对Comctl32.DLL版本的描述。若没有相关描述,系统加载默认版本的Comctl32.DLL。如果Manifest中声明了需要加载Comctl32.DLL 6.0版本,则对应版本Comctl32.DLL就会被加载。下图描述了应用程序加载DLL的过程:

1a92c3c1a6e602e9e12ae62c82bbb3af

微软推荐我们使用并行程序集技术,基于下面几个原因:

  1. 并行程序集技术可以很大程度上避免了不同DLL版本之间的冲突
  2. 并行程序集技术可以使多个不同版本的COM、Windows程序集同时运行
  3. 系统管理员可以更新应用程序依赖的程序集,而不需要重新安装应用程序

Manifest文件

Manifest文件通常包括三部分组成,Assembly Manifests(程序集清单),Application Manifests(应用程序清单),Publisher Configuration Files (发行者配置文件),下面简单介绍各自的作用。

Assembly Manifests(程序集清单)

Assembly Manifests是一个XML文件用于描述一个并行程序集的名字,版本号,文件,资源和它对其他程序集的依赖。这里使用Visual C++ 2005的C Runtime (CRT)库的运行时组件举例说明,这个程序集属于共享程序集(Shared Assembly),安装完成可再发行组件包可以在%windir%/WinSxs/Manifest目录中找到这个配置文件。在Windows 7系统中对应的文件名为:

x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.4053_none_d08d7da0442a985d.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.4053″ processorArchitecture=”x86″ publicKeyToken=”1fc8b3b9a1e18e3b”>
</assemblyIdentity>
<file name=”msvcr80.dll” hash=”0a38b652c9d03caab803c6b2505fa301e345bab2″ hashalg=”SHA1″></file>
<file name=”msvcp80.dll” hash=”678bf3da5d1987bb88fd47c4801ecb41f51366ef” hashalg=”SHA1″></file>
<file name=”msvcm80.dll” hash=”34f57d3d73b2810fa7b5ddc111898f137bc0530b” hashalg=”SHA1″></file>
</assembly>

assemblyIdentity元素用于唯一定义一个程序集,包括名称、版本、类型等关键信息。File元素用于定义程序集包括哪些文件,从XML可以看出Visual C++ 2005的C Runtime (CRT)库程序集包括msvcr80.dll msvcp80.dll msvcm80.dll三个文件。除了可以定义DLL信息,还可以定义DLL中包含的COM组件,具体内容可以参考MSDN。

Application Manifests(应用程序清单)

Application Manifests描述的是应用程序在运行时需要加载哪个程序集,同时还指定了应用程序需要版本号。Application Manifests是保存在EXE或者DLL文件的资源中。这里拿QQ.exe的Manifest资源举例说明。

<assembly xmlns=”urn:schemas-microsoft-com:asm.v1″ manifestVersion=”1.0″>
<assemblyIdentity version=”1.0.0.0″ processorArchitecture=”X86″ name=”Tencent.QQ” type=”win32″></assemblyIdentity>
<description></description>
<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.VC80.CRT” version=”8.0.50727.4053″ processorArchitecture=”x86″ publicKeyToken=”1fc8b3b9a1e18e3b”></assemblyIdentity>
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity type=”win32″ name=”Microsoft.VC80.ATL” version=”8.0.50727.4053″ processorArchitecture=”x86″ publicKeyToken=”1fc8b3b9a1e18e3b”></assemblyIdentity>
</dependentAssembly>
</dependency>
<trustInfo xmlns=”urn:schemas-microsoft-com:asm.v3″>
<security>
<requestedPrivileges>
<requestedExecutionLevel level=”asInvoker” uiAccess=”false”></requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

dependency元素中至少包括一个dependentAssembly,dependentAssembly用于描述应用程序依赖的程序集,assemblyIdentity 元素的内容于Assembly Manifests文件中定义的assemblyIdentity 元素相对应,从QQ.exe的Manifest配置可以看出,QQ应用程序依赖版本号为8.0.50727.4053的Microsoft.VC80.CRT并行程序集。

Publisher Configuration Files(发行者配置文件)

Publisher Configuration Files同样也是一个 XML 文件,它对应用程序和程序集进行全局重定向,使其从使用并行程序集的一个版本变为使用该程序集的另一个版本。下面是一个很好的示例说明配置文件的作用:发行者为特定的并行程序集修复了Bug或安全漏洞,而且此程序集的发行者希望让系统上所有的应用程序以使用新版本的程序集,开发者之需要修改配置文件文件,它将对对特定的应用程序进行重定向。原本依赖旧版本程序集的应用程序,将会加载该程序集的新版本。我们继续使用Visual C++ 2005的C Runtime (CRT)库的运行时组件举例说明,路径在%windir%/WinSxs/Manifest下找到文件x86_policy.8.0.microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.4053_none_516e2e610f48bda6.manifest。

<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>
<!– Copyright © 1981-2001 Microsoft Corporation –>
<assembly xmlns=”urn:schemas-microsoft-com:asm.v1″ manifestVersion=”1.0″>
<assemblyIdentity type=”win32-policy” name=”policy.8.0.Microsoft.VC80.CRT” version=”8.0.50727.4053″ processorArchitecture=”x86″ publicKeyToken=”1fc8b3b9a1e18e3b”/>
<dependency>
<dependentAssembly>
<assemblyIdentity type=”win32″ name=”Microsoft.VC80.CRT” processorArchitecture=”x86″ publicKeyToken=”1fc8b3b9a1e18e3b”/>
<bindingRedirect oldVersion=”8.0.41204.256-8.0.50608.0″ newVersion=”8.0.50727.4053″/>
<bindingRedirect oldVersion=”8.0.50727.42-8.0.50727.4053″ newVersion=”8.0.50727.053″/>
</dependentAssembly>
</dependency>
</assembly>

bindingRedirect是这里的关键元素,包含了程序集的重定向关系,oldVersion使用之间的程序集会被重定向到newVersion指定的版本号。

现在Manifest中三个文件各自的作用清晰了,Assembly Manifest用于定义一个并行程序集,Application Manifest描述了应用程序需要使用哪些并行程序集,Publisher Configuration Files在其中起到重定向作用,比如Application Manifest指定了一个旧版本的程序集,通过Publisher Configuration Files配置信息,某个新版本的程序集可以代替旧版本的,这时应用程序会加载较新版本的。

可惜的是微软已经开始放弃并行程序集技术,Visual C++ 2010运行库没有使用并行程序集技术部署,而是倒退回Windows 2000那样,直接就把DLL文件放在软件目录下面,或者安装到系统目录下面。我想原因可能是并行程序集技术带来的一些不方便引起的,如调试程序时候,你想使用特定版本的程序集,你不能直接把文件放在目录下面,你需要配置相关的Manifest文件后才可以使用。部署的时候如果按照微软推荐的方法必须使用Windows Installer来部署,现在大多软件都不使用Windows Installer制作安装包了,当然也有可以不使用Windows Installer的方法,不过MSDN上面并没有相信说明这个方法。

如果没有使用并行程序集技术就必须回到文章开头的说明的问题,不同DLL版本必须做到完全兼容,否则会出现问题。对于我们自己开发的程序集,我们仍然可以使用并行程序集技术,未来Windows版本仍然对这个特性支持。

Manifest文件其他用途

从Vista开始,Application Manifest又有了新的内容了。新增的requestedExecutionLevel元素可以让开发者指定应用程序执行的权限。

<requestedExecutionLevel level=”asInvoker|highestAvailable|requireAdministrator” uiAccess=”true|false”/>

level三种值中,asInvoker表示应用程序将以父进程的访问权限启动。highestAvailable会以当前用户的最高权限启动程序。requireAdministrator则会以管理员权限启动运行程序。这里的值会与User Account Control(用户账户控制)所设置的值有关系,不同的设置会影响到不同的界面和权限表现,具体内容可以参考MSDN。

设置requestedExecutionLevel对于安装程序或者一些自解压的安装程序来说非常重要,如果没有设置requestedExecutionLevel一般情况下无法获得管理员权限,导致程序无法正确安装,或者Windows系统可能会弹出程序兼容性助手对话框,如下图:

image002

如果用户选择了“Reinstall using recommended settings”系统将会以Windows XP SP2兼容模式重新启动应用程序。

程序兼容性助手是如何检测一个安装程序是否成功安装了?Windows会判断运行的程序是否是安装程序,如果是安装程序Windows会监控程序是否注册了新的添加删除项,如果有新增项,就认为程序安装成功了,没有则认为安装失败。

在Windows Vista下为应用程序设置了requestedExecutionLevel,Program Compatibility Assistant(程序兼容性助手)就不会出现了,但是在Windows 7下发现有时候还是会出现程序兼容性助手对话框。

如果需要在Windows 7、Windows 8下解决这个问题,需要在Manifest配置一个新增项。

<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>
<assembly xmlns=”urn:schemas-microsoft-com:asm.v1″ manifestVersion=”1.0″>
<compatibility xmlns=”urn:schemas-microsoft-com:compatibility.v1″>
<application>
<!–The ID below indicates app support for Windows Vista –>
<supportedOS Id=”{e2011457-1546-43c5-a5fe-008deee3d3f0}”/>
<!–The ID below indicates app support for Windows 7 –>
<supportedOS Id=”{35138b9a-5d96-4fbd-8e2d-a2440225f93a}”/>
<!–The ID below indicates app support for Windows Developer Preview –>
<supportedOS Id=”{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}”/>
</application>
</compatibility>
</assembly>

Compatibility项用于告诉系统该应用程序是基于哪个版本的操作系统开发的,如果并且让指定系统的特性生效。这个特性可以让操作系统为新开发的程序提供新的特性,并且对以前开发、设计的程序保持兼容。在Windows 7和以后的操作系统中下,若没有Compatibility项,系统将提供与Windows Vista兼容的行为。而Windows XP和Windows Vista会忽略Compatibility项。

在Windows 7、Windows 8下应用程序配置了Compatibility项,兼容程序兼容性助手就不会再出现了。

Vista开始Manifest还可以说明应用程序是否支持高DPI。

<assembly xmlns=”urn:schemas-microsoft-com:asm.v1″ manifestVersion=”1.0″ xmlns:asmv3=”urn:schemas-microsoft-com:asm.v3″ >
<asmv3:application>
<asmv3:windowsSettings xmlns=”http://schemas.microsoft.com/SMI/2005/WindowsSettings”>
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>

只要再manifest文件中加入上面这一段XML,就将描述为应用程序支持高DPI。当然这样并不代表你的程序就支持了高DPI显示,最大的区别是关掉了DPI Virtualization支持。具体如何让应用程序支持高DPI可以参考微软的这篇文档《Writing High-DPI Win32 Applications》。



只回答业务咨询点击这里给我发消息 点击这里给我发消息

学习日记,兼职软件设计,软件修改,毕业设计。

本文出自 学习日记,转载时请注明出处及相应链接。

本文永久链接: https://www.softwareace.cn/?p=1207

0

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">


Ɣ回顶部

无觅相关文章插件,快速提升流量