Chapter3 共享程序集和强命名程序集

1.1两种程序集,两种部署

哪两种程序集?
CLR支持两种程序集:弱命名程序集(weakly named assembly)和强命名程序集(strongly named assembly)
两种程序集的共同点?
结构上完全一致:相同的PE文件格式、PE32(+)头、CLR头、元数据、清单表以及IL。
生成工具相同:C#编译器或者AL.exe
两种程序集的区别?
强命名程序集使用了发布者的公钥/私钥对进行了签名,它唯一标识了程序集的发布者,这对密钥允许对程序集进行唯一性的标识、保护和版本控制,允许程序集部署到用户机器的任何地方,甚至可以部署到Interne。
上面介绍了两种程序集,下面在介绍两种部署
一个程序集可以采取两种方式来部署:
1.私有,私有部署的程序集:指部署到应用程序基目录或者一个子目录中的程序集,(弱命名程序集只能以私有的方式部署)。
2.全局,全局部署的程序集:指部署到一些已知位置的程序集。(强命名程序集既可以私有部署,也可以全局部署)

1.2为程序集分配强名称

一个强命名程序集具有4个重要的Attributes,它们对程序集进行了唯一性标识:
①一个文件名(不计扩展名)
②一个版本号
③一个语言文化标识
④一个公钥(公钥标记public key token,小的哈希值)
例如:

"MyTypes, Version=1.0.8123.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
"MyTypes, Version=1.0.8123.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"

以上标识了2个完全不同的程序集文件
这样一来,两家公司就可以创建具有相同名称、版本和语言文化的程序集,同时不会造成任何冲突
生成一个公钥/私钥对:
1.使用SN.exe来获取一个密钥

SN -k MyCompany.snk

这个命令行告诉SN.exe创建一个名为MyCompany.snk的文件,文件中包含二进制形式的公钥和私钥
2.创建一个只包含公钥的文件(从MyCompany.snk文件中提取公钥并将其存储在MyCompany.PublicKey中)

SN -p MyCompany.snk MyCompany.PublicKey

3.显示公钥和MyCompany.snk包含的公钥的标记

SN -tp MyCompany.PublicKey

1.3全局程序集缓存

如果一个程序集要由多个应用程序访问,必须把它放到一个已知的目录中,而且CLR在检测到对该程序集的一个引用时,必须知道自动检查该目录,这个已知的目录成为全局程序集缓存(GAC)
.net 3.5和以前版本GAC通常位于C:\Windows\Assembly
.net 4.0位于C:\Windows\Microsoft.NET\Assembly
不要尝试手动复制程序集文件到GAC目录中,相反需要用GACUtil.exe工具在GAC中安装一个强命名程序集(注意弱命名程序集不能放到GAC中)

1.4在生成的程序集中引用一个强命名程序集

利用csc.exe 的/reference开关来指定想要引用的程序集文件名
如果文件名是个完整的路径,csc.exe会加载指定的文件,并根据它的元数据来生成程序集
如果只是单纯的一个文件名,则csc.exe会尝试在以下目录查找需要引用的程序集(按所列出的顺序):
1.工作目录
2.包含CSC.exe本身的目录,目录中还包含CLR的各种DLL文件
3.使用/lib编译器开关指定的任何目录
4.使用LIB环境变量指定的任何目录

1.5强命名程序集能防范篡改

用一个私钥对程序集进行签名,可以保证程序集是由对应公钥的持有者生成的。程序集安装到GAC时,系统对包含清单的那个文件的内容进行哈希处理,并将哈希值与PE文件中签入的RSA数字签证进行比较,如果两个值完全一致,表明文件内容未被篡改。

1.6延迟签名

当准备对自己的强命名程序集进行打包时,必须使用受到严密保护的私钥(大企业们会把它放到硬件设备中比如智能卡)对它进行签名。
然而在开发和测试程序集时,访问这些私钥可能有些费事,所以.net framework提供了对延迟签名的支持。
延迟签名允许你只能用公司的公钥来生成一个程序集,暂时不用私钥。在打包和部署程序集时,肯定会签名的。
使用延迟签名技术开发程序集的步骤:
1.开发程序集期间,获取只包含你的公司的公钥的一个文件,使用/keyfile和/delaysign编译器开关编译程序集:
csc /keyfile:MyCompany.PublicKey /delaysign MyAssembly.cs
2.生成程序集之后,执行以下命令,使CLR暂时信任程序集的内容,不对它进行哈希处理,也不比较哈希值,使其顺利的安装到GAC(如果有必要的话),现在可以生成引用这个程序集的其他程序集了,并可以随意测试。注意:在每台开发用的机器上,以下命令行都只需执行一次
SN.exe -Vr MyAssembly.dll
3.准备好打开和部署程序集时,请获取你的公司的私钥,然后执行以下命令,如果愿意,可以将这个新版本安装到GAC中
SN.exe -R MyAssembly.dll MyCompany.PrivateKey
4.为了在实际环境中测试,请执行以下命令,重新启动对这个程序集的验证:
SN.exe -Vu MyAssembly.dll

1.7私有部署强命名程序集

在GAC中安装程序集具有几方面优势?
1.GAC使程序集能被多个应用程序共享,减少总体物理内存占用
2.很容部署一个新版本的程序集到GAC中,让所有应用程序通过一个发布者策略来使用这个新版本
3.GAC还实现了对程序集多个版本的并行管理

1.8运行时如何解析类型引用

解析一个引用类型时,CLR可能以下三个地方找到类型
1.同一个文件,编译时发现对相同文件中的类型访问
2.不同文件,同一程序集
3.不同的文件,不同的程序集
解析一个引用类型时,如果发生任何错误(比如找不到文件、文件无法加载、哈希值不匹配等),就会抛出一个相应的异常。
如下图:基于引用了一个方法或类型的IL代码,CLR如何利用元数据来定位一个类型定义的程序集

1.9高级管理控制(配置)

CLR如何利用XML配置文件来定位移动的文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<assemblyBinding >
<probing privatePath="AuxFiles;bin\subdir" xmlns="urn:schemas-microsoft-com:asm.v1"/>
<dependentAssembly>
<assemblyIdentity name="JeffTypes" publicKeyToken="32ab4ba45e0a69a1" culture="neutural"/>
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
<codeBase version="2.0.0.0" href="http://www.Wintellect.com/JeffTypes.dll"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="TypeLib" publicKeyToken="1f2e74e897abbcfe" culture="neutural"/>
<bindingRedirect oldVersion="3.0.0.0-3.5.0.0" newVersion="4.0.0.0"/>
<publisherPolicy apply="no"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

1.probing元素
查找一个弱命名程序集时,检查应用程序基目录AuxFiles和bin\subdir子目录。对于一个强命名程序集,CLR会检查GAC或由codeBase元素指定的URL。如果没有指定codeBase元素,CLR才会在应用程序的私有路径中检查强命名的程序集
2.第一个dependentAssembly、assemblyIdentity、bindingRedirect元素
查找控制着公钥标识32ab4ba45e0a69a1的那个组织发布的、语言文化为中性的JeffTypes程序集的1.0.0.0版本时,改为同一个程序集的2.0.0.0版本
3.codeBase元素:查找由控制着公钥标识32ab4ba45e0a69a1的组织发布的、语言文化为中性的JeffTypes程序集的2.0.0.0版本时,尝试在URL处发现它http://www.Wintellect.com/JeffTypes.dll
4.第二个dependentAssembly、assemblyIdentity、bindingRedirect元素
查找由控制这公钥标识为1f2e74e897abbcfe的那个组织发布的、语言文化为中性的TypeLib程序集的3.0.0.0到3.5.0.0版本时,改为定位同一个程序集的4.0.0.0版本
5.publisherPolicy元素
如果生成TypeLib程序集的组织部署了一个发布者策略文件,CLR应该忽略该文件

发布者策略控制

例如企业刚刚创建了一个程序集的新版本,并修复了几个bug,打包要发送给所有用户的新程序集时,应同时创建一个XML配置文件,和上面的差不多,
现在作为发布者,可创建包含这个发布者策略配置文件的一个程序集,为了创建发布者策略程序集,要像下面这样运行AL.exe
AL.exe /out:Policy.1.0.JeffTypes.dll
/version:1.0.0.0
/keyfile:MyCompany.snk
/linkresource:JeffTypes.config
/out 开关指示AL.exe创建一个新的PE文件,本例就是Policy.1.0.JeffTypes.dll
/version 开关标识发布者策略程序集的版本,这个与JeffTypes程序集本身无关。
/keyfile 开关指示AL.exe使用发布者的“公钥/私钥”对发布者策略程序集进行签名,这个密钥必须匹配于所有JeffTypes程序集版本
/linkresource 开关告诉AL.exe将XML配置文件作为一个资源连接(而非嵌入)到程序集
如果新的程序集引入的bug比修复的bug还要多,可以忽略发布者策略程序集
<publisherPolicy apply="no"/>

原文地址:https://www.cnblogs.com/hailiang2013/p/2853351.html