Visual Studio安装程序会把Visual Studio的共享库放在一个称为\\\\\\\"并列缓存\\\\\\\"的地方,那怎样才能有效地利用它呢?
版本重定向
回过头来再看一下为库创建的清单文件,注意程序集所需的版本号给定为8.0.50608.0,再次提醒,Visual Studio 2005安装的程序集是8.0.50727.42,这个叫策略版本重定向。在并列缓存的同级Policies目录中,可找到下面这个文件夹:
x86_policy.8.0.Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_x-ww_77c24773 |
注意,除了版本部分,它有着程序集的全名。此文件夹中分别包含了一个策略及安全编目文件,文件名基于将要重定向至的版本号:
8.0.50727.42.policy
这是一个XML文件(见例5)。这个策略文件是针对版本8.0.50727.42的,其也是Visual Studio安装程序所安装的版本。它在<bindingRedirect>中指明了所有将要被重定向至本版本的版本号,例5中表明,对版本号8.0.41204.256至8.0.50608.0程序集的所有请求,都会被重定向至8.0.50727.42这个版本。与Fusion(混淆: .NET中的程序集加载技术)不同的是,对并列共享程序集的版本重定向只能是那些生成或修订的版本值之间的变化,不能用于主、副版本值的变化。
例5:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!-- Copyright (r) 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.42" 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.42"/> </dependentAssembly> </dependency> </assembly> |
那就又带出了一个问题:那为什么需要重定向呢?为什么链接器不在清单文件中直接指定由安装程序安装的程序集版本呢?原因在于,链接器是从导入静态库中获得所需的程序集版本。这又引出了另外一个问题:为什么链接器要为DLL的不同版本使用导入库,而不是安装的那个?原因是,这些安装的都是重要的库。
目前为止的讨论都是针对托管C++编译器(C++/CLI及旧式语法),然而,即便本地C++开发技巧再高,也有可能被这些新"特性"所影响。如果你的代码使用了某个共享的Visual Studio本地库(MFC、ATL或CRT),那么,必须有一个单独的.manifest清单文件,要么绑定至可执行文件,要么只绑定至一个 .exe文件。
结论 以前Microsoft C++编译器及链接器的各个版本所生成的库,都能被Windows加载并运行,但Visual Studio 2005中的版本14,生成的库却无法运行。
此处有两个解决方法:第一种方法是运行链接器两次,一次是生成清单文件,其能编译进非托管资源,接着一次是把这个清单绑定至PE文件。这也是本文所推荐的方法,因为如果在构造一个具有"强名称"的程序集,在第二次调用时,就能提供密钥文件或容器的名称。
另一个方法是,使用mt.exe未公开的选项来修改程序集,然而,如果使用链接器来生成一个"强名称"的程序集,mt.exe的动作会使强名称签名无效,且程序集也不会加载。
查看本文来源