生成 C/C++ 并行程序集
side-by-side assembly是应用程序在运行时可使用的资源的集合,如一组 DLL、Windows 类、COM 服务器、类型库或接口。在 Visual C++ 2005 中,已将 ATL 库、MFC 库、标准 C++ 库和 CRT 库重新打包到若干个并行程序集中,这些程序集可以通过 Visual C++ 应用程序重新发布为共享或私有程序集。有关更多信息,请参见Visual C++ Libraries as Shared Side-by-Side Assemblies。将 DLL 重新打包到程序集中的主要优点是,应用程序可以同时使用程序集的多个版本,且发布更新时可以为当前已安装的程序集提供服务。
Visual C++ 应用程序可以在它的不同部分使用一个或若干个 DLL。运行时,会将这些 DLL 加载到主进程并执行所需的代码。应用程序依赖操作系统来定位所需的 DLL,了解必须加载的其他依赖 DLL,然后将它们与所需的 DLL 一起加载。在早于 Windows XP 和 Windows 2003 版本的 Windows 操作系统上,操作系统加载程序会在应用程序的本地文件夹或系统路径指定的另一个文件夹中搜索依赖 DLL。在 Windows XP 和 Windows 2003 上,操作系统加载程序还可以使用manifest文件搜索依赖 DLL,并搜索包含这些 DLL 的并行程序集。
默认情况下,在使用 Visual Studio 2005 生成 DLL 时,该 DLL 会有一个作为 RT_MANIFEST 资源(ID 等于 2)嵌入的application manifest。正如可执行文件一样,此清单描述该 DLL 在其他程序集中的依赖项。此处假定此 DLL 不是并行程序集的一部分,且依赖于此 DLL 的应用程序将不会使用应用程序清单加载此 DLL,而是依靠操作系统加载程序在系统路径中查找此 DLL。
注意 |
---|
对于使用应用程序清单的 DLL 来说,将此清单作为资源(ID 等于 2)嵌入其中,是十分重要的。如果在运行时动态加载此 DLL(例如,使用LoadLibrary函数),操作系统加载程序将加载 DLL 的清单中指定的依赖程序集。在调用LoadLibrary期间,不会检查 DLL 的外部应用程序清单。如果未嵌入此清单,则加载程序可能会试图加载程序集的错误版本,或无法找到依赖程序集。 |
通过相应的assembly manifest,可以将一个或若干个相关 DLL 重新包装到并行程序集中,该清单用于描述构成此程序集的文件、以及此程序集对于其他并行程序集的依赖性。
此更改允许将相应的 DLL 作为private assembly部署到应用程序本地文件夹中,或作为shared assembly部署到 WinSxS 程序集缓存中。若要使此新程序集在运行时的行为准确无误,必须执行若干步骤;Guidelines for Creating Side-by-side Assemblies中对这些步骤进行了描述。正确编写程序集后,可将此程序集作为共享程序集或私有程序集与依赖于它的应用程序一起进行部署。将并行程序集作为共享程序集安装时,可以按照Installing Win32 Assemblies for Side-by-Side Sharing on Windows XP中介绍的指南进行操作,也可以使用merge modules。将并行程序集作为私有程序集安装时,在安装过程中,仅需将相应的 DLL、资源和程序集清单复制到目标计算机上的应用程序本地文件夹中,这样可确保加载程序在运行时可以找到此程序集(请参见Assembly Searching Sequence)。另一种方法是使用Windows Installer,并按照Installing Win32 Assemblies for the Private Use of an Application on Windows XP中介绍的指南进行操作。
相关章节
请参见
Windows XP通过XML文件来实现这一功能,这些XML文件保存了有关应用程序配置的元数据,这里所说的XML文件,就是Manifest清单文件。
Manifest事实上就是一个以.manifest为后缀的XML文件,用于组织和描述隔离应用程序及并行组件,其内部的信息如<assemblyIdentity>元素则标识着一个唯一的程序集,和其他信息一起,他们用于COM类、接口及库的绑定和激活,而这些信息,以往都是存储在注册表中的。另外,Manifests也制定了组成程序集的文件及Windows类。
一、Manifest的分类
在Windows XP中,事实上是在.NET中,把Manifests分类为如下几种类型:
1、程序集Manifests(Assembly Manifests):主要用于描述程序集,管理程序集的名字、版本、资源、依赖程序集。其中共享程序集的Manifests存储在Windows的WinSxS目录中。私有的程序集Manifests则存可以作为一个资源存储在DLL中,也可以存储在应用程序目录下。
2、应用程序Manifests(Application Manifests):这类Manifests则用于描述隔离应用程序,它管理着此应用程序在运行时要绑定的共享的并行组件的名字、版本。该Manifests可以作为一个文件(.manifest文件)存储在应用程序相同的目录下,也可以作为一种资源嵌入在可执行文件内部(Embed Manifest)。
3、应用程序配置文件(Application Configuration Files):对于并行组件及隔离应用程序来说,使用这种Manifests来“Override and Redirect”所依赖程序集的版本。
4、发行配置文件(Publisher Configuration Files):用于重定向并行组件的版本倒另外一个合适的版本的Manifests。此时,被重定向的新程序集应该和原来的旧程序集具有相同的主.次(majou.minor)版本号。
二、Windows对于Manifest的处理
XP以前版本的windows,会像以前那样执行这个exe文件,寻找相应的dll,没有分别,Manifest只是个多余的文件或资源,dll文件会直接到system32的目录下查找,并且调用。
而XP及其以后的操作系统,则会首先读取Manifest,获得exe文件需要调用的DLL列表(此时获得的,并不直接是DLL文件的本身的位置,而是DLL的manifest)操作系统再根据DLL的Manifest提供的信息去寻找对应的DLL ,这样就可能区别不同版本的同一个DLL文件。
这就说明了为什么我的程序可以在2000下面运行,而在XP及2003上无法运行。这也使得很多木马可以利用这个特点实现限制安全软件。
三、VS2005种的Manifest配置
使用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 等,那么你可以不需要考虑Manifest, 可以关掉它。此时,在VS2005种中,project的设置必须是Use Standard Windows Libraries、Not Using ATL、No Common Language Runtime support。
开心