什么是Side-by-Side Assembly?
Side-by-Side Assembly按照我的理解,是一种特殊的DLL,按照Side-by-Side Assembly的要求开发的,并用XML格式的manifest和policy文件描述的。所有的系统Side-by-Side Assembly都安装在Windows目录下的WinSxS子目录里,有一堆的目录、DLL和XML文件。
使用Side-by-Side Assembly包括两个方面,一方面是自己开发的应用程序和DLL如何依赖Side-by-Side Assembly,另一方面是如何开发自己的Side-by-Side Assembly。如果只关心第一个方面,问题要简单的多。不需要关心第二个方面的原因如下。
Visual Studio 2010要取消对Side-by-Side Assembly的默认支持?
当然SxS还是有的,应该只是Visual Studio不再在开发应用时默认采用。
应用如何依赖Side-by-Side Assembly
cl.exe在链接生成EXE的时候,会同时生成一个同名的manifest文件。该文件是XML格式的,描述了EXE对SxS的依赖。下面是一个manifest的例子:
<?xmlversion="2.0"encoding="UTF-8"standalone="yes"?>
<assemblyxmlns="urn:schemas-microsoft-com:asm.v1"manifestversion="1.0">
<trustinfoxmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedprivileges>
<requestedexecutionleveluiaccess="false"level="asInvoker"></requestedexecutionlevel>
</requestedprivileges>
</security>
</trustinfo>
<dependency>
<dependentassembly>
<assemblyidentityname="Microsoft.VC90.CRT"publickeytoken="1fc8b3b9a1e18e3b"processorarchitecture="x86"version="9.0.21022.8"type="win32"></assemblyidentity>
</dependentassembly>
</dependency>
</assembly>
如果删除这个manifest文件,运行该EXE会出现类似下面的错误:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiInBnauM2Y2Q2YkFGZ2UDOzMmY0ATOwczNlJjYzQGN0YTM1QjZfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.jpg)
这是因为缺少manifest文件的描述,程序不知道如何载入WinSxS目录下的DLL。所以最好把manifest文件嵌入EXE中,可以用mt.exe工具完成这一工作:
mt.exe -manifest <manifest-file> -outputresource:<exe-file>;#1
用IDE开发不存在这个问题,IDE会自动调用mt.exe将manifest嵌入EXE
DLL如何依赖Side-by-Side Assembly
mt.exe -manifest <manifest-file> -outputresource:<dll-file>;#2
用IDE开发也不存在这个问题,IDE会自动调用mt.exe将manifest嵌入DLL
如何绕过Side-by-Side Assembly?
Side-by-Side Assembly带来了很多不便,比如说,依赖SxS MSVCR90.dll的程序在没有安装VC redistributable的系统中不能运行,像是WinPE环境。因此最好有一种绕过SxS的方法,将SxS的Assembly和EXE放在一个目录下,避免依赖系统WinSxS目录下的Assembly。
1. 首先,我们需要manifest文件,如果手头没有EXE和DLL的manifest文件,可以用mt.exe工具从EXE和DLL中导出manifest文件
导出EXE的manifest
mt.exe -inputresource:<exe-file>;#1 -out:<manifest-file>
导出DLL的manifest
mt.exe -outputresource:<dll-file>;#2 -out:<manifest-file>
2. 根据manifest中的信息,创建若干新的manifest文件。新manifest文件名和EXE中依赖的Assembly名字对应,例如按照前面的manifest例子,应该对应创建一个Microsoft.VC90.CRT.manifest,内容格式如下:
<noinheritable></noinheritable>
<filename="msvcr90.dll"></file>
<filename="msvcp90.dll"></file>
其中assemblyIdentity和原EXE的内容要完全一样。
3. 根据manifest文件中的assemblyIdentity信息,到系统的WinSxS目录下的子目录里找DLL,子目录名的格式是<processorArchchitecture>-<name>-<publicKeyToken>-<version>-none-xxx。把子目录下的DLL拷贝到EXE所在的目录下。把DLL的名字写入新manifest的file标签下。
至此,已经把Assembly放到EXE所在目录下,EXE也不再依赖系统WinSxS目录下的Assembly了。
VC 2005和VC 2008相关的SxS打包