【转】C#程序集

           1.程序集是一个或多个托管模块,以及一些资源文件的逻辑组合。
           2.程序集是组件复用,以及实施安全策略和版本策略的最小单位。
           3.程序集是包含一个或者多个类型定义文件和资
程序集的定义:
           1.程序集是一个或多个托管模块,以及一些资源文件的逻辑组合。
           2.程序集是组件复用,以及实施安全策略和版本策略的最小单位。
           3.程序集是包含一个或者多个类型定义文件和资源文件的集合。在程序集包含的所有文件中,有一个文件用于 保存清单。(清单是元数据部分中一组数据表的集合,其中包含了程序集中一部分文件的名称,描述了程序集的 版本,语言文化,发布者,共有导出类型,以及组成该程序集的所有文件)。

 程序集的物理表现:
           1.可执行程序集:存在一个用于表示EXE的文件,这个文件是程序集的入口点。
           2.提供功能的程序集:存在一个用于表示DLL的文件,这个文件是程序集的入口点。

程序集和托管模块的关系:
           1.可以使用       csc   /t:module       type1.cs  
                                     csc   /t:module       type2.cs  
                                     这样就可以生成两个托管模块: type1.netmodule  type2.netmodule
          2.使用命令将模块集成到程序集中:
                                     csc  /out:xxx.dll       /t:library  /addmodule: type1.netmodule type2.netmodule xxx.cs
           这样就有了程序集xxx.dll:    它由xxx.dll type1.netmodule type2.netmodule 组成。xxx.dll代表了这组程序集。xxx.dll也可以是xxx.exe。也可以使用al来创建:
          Al /out:xxx.dll /t:library type1.netmodule type2.netmodule.
         3.卫星程序集:
                 3.1创建资源文件:MyResource.cn.Resx 或者MyResource.cn.txt
                 3.2使用命令resgen MyResource.cn.resx  MyResource.cn.resources 编译资源          
                 3.3   al.exe /culture:cn /out:"cn\HelloWorld.Resources.dll" /embed:"MyResources.cn.resources" /template:"HelloWorld.exe"           
                 3.4在主程序集HelloWorld中如何访问卫星程序集:
                    System.Resources.ResourceManager resources =
                    new System.Resources.ResourceManager("HelloWorld.Resources.MyResources",
                    System.Reflection.Assembly.GetExecutingAssembly());

                // Print out the "HelloWorld" resource string
                Console.WriteLine(resources.GetString("HelloWorld"));
               
                // Get the new culture name
                Console.Write(resources.GetString("NextCulture"));
                3.5部署主程序集和卫星程序集 
│  HelloWorld.exe
├─ko-kr
│      HelloWorld.resources.dll
├─it
│      HelloWorld.resources.dll
├─fr
│      HelloWorld.resources.dll
├─es
│      HelloWorld.resources.dll
├─en
│      HelloWorld.resources.dll
├─en-us
│      HelloWorld.resources.dll
└─de
       HelloWorld.resources.dll

通过AL工具来改变一个程序集的各种属性:
        可以参见AL的帮助
通过AssemblyInfo.cs文件来改变一个程序集的属性:
       这个文件中最重要的几个特性是:
              1、AssemblyVersion: 格式: Major Version ---- Minor  Version ------ Build  version ------  Revision
              2、[assembly: AssemblyCulture("")]   
              3、[assembly: AssemblyDelaySign(false)]
              4、[assembly: AssemblyKeyFile("")]
              5、[assembly: AssemblyKeyName("")]
      这几个各个程序集属性的探讨

将程序集组成各种应用程序,进行程序集的部署:
       不考虑应用程序的类型,可以将程序集的部署分为私有部署和全局部署。
       私有部署:
           1.本地应用程序的部署结构
                 AppDir
                   |---- App.exe
                   |---- App.exe.config
                   |-----AuxFilesDir
                             |------ xxx.dll
                             |------ yyy.dll
                  在App.exe.config中可以配置影响CLR寻找程序集路径的选项。
           2.Asp.net应用程序和XML Web服务应用程序
                对于asp.net Web窗口和XMLWeb服务应用程序,配置文件必须位于Web应用程序的虚拟根目录下,并且名称总是Web.config 。另外子目录也可以包含它们自己的Web.config文件,并继承上一目录的配置设置。
           3. 对于包含客户方空件、以微软的IE浏览器为宿主的程序集。(没有见过)
      
         全局部署:(这里部署的都是强命名程序集)
             CLR需要支持某种机制来唯一标识程序集。一个强命名程序集包含四个唯一标识程序集的特性:文件名(没有扩展名)、版本号(assemblyversion)、语言文化标识和一个公有密钥标记(由公有密钥产生的一个值)。
              这四个信息都存储在AssemblyDef 中,其结构示意如下:
               Assembly
               ------------------------
                Token: 0x200001
                Name: xxxxx
                Public Key: yyyyyyy
                HashAlgorithm: 0x00008004
                Major Version: 0x000001
                Minor Version: 0x000000
                Build  Number: 0x00000253
                Revision Number: 0x00005361
                Locale: <null>
                Flags:
          生成一个强命名程序集的步骤如下:
               1、使用SN  -k MyCompany.keys    生成名为MyCompany.keys文件,该文件包含一对以二进制存储的共有密钥和私有密钥。
              2、查看共有密钥的命令: SN -p MyCompany.keys MyCompany.PublicKey
                                                          SN -tp MyCompany.PublicKey
              3、使用特性 System.Reflection.AssemblyKeyFileAttribute将公私密钥对程序集进行签名。
                 [assembly:AssemblyKeyFile("MyCompany.keys")]
              4、编译器或者AL使用公私密钥进行签名的过程如下:
                当生成一个强命名程序集时,该程序集的FileDef清单元数据表将包含组成该程序集的所有文件的一个列表。当一个文件的名称被加入到清单中时,该文件的内容也被转换成一个散列值,该散列值将和文件名一起存入到FileDef表中。(这里使用的散列算法可以使用AL  /algid 命令开关来改变,或者 System.Reflection.AssebmlyAlgorithmIdAttribute定制特性来改变默认的散列算法(SHA-1)。
               在生成包含清单的PE文件之后,该PE文件的整个内容都被转换成一个散列值,这里使用的算法总是SHA-1,不能够改变。该散列值经由发布者的私有密钥签名,生成的RSA数字签名被存储在PE文件的一个保留区域中(该保留区存在于CLR表头中)
               另外发布者的共有密钥也被嵌入到AssebmlyDef清单元数据表中。
       (密码学中的规则应用:使用密钥签名,使用公钥解密验证。验证过程:使用同样的过程将文件进行散列,最后将包含清单的文件进行散列,得出的散列值与使用公钥解密散列签名得出的散列值进行比较。)
             
              共享程序集的延迟签名:
               使用延迟签名的理由:公司的私钥需要安全存储,大多数公司都不允许所有的开发人员访问私钥。只有几个有安全权限的人才能访问。
               程序集的延迟签名需要执行下面的步骤:
                 1.首先必须用sn 创建一个公共/私匙对,生成mykey.snk:
                          sn -k  mykey.snk
                 2.提取公钥,使之可以用于开发人员:
                     sn -p mykey.snk mypublic.snk
                    在文件AssemblyInfo.cs中设置AssemblyDelaySign和AssemblyKeyFile属性:
                    [assembly: AssemblyDelaySign(true)]
                    [assembly:AssemblyKeyFile("mypublickey.snk")]]
                    如果使用AL 工具则可以使用如下选项来实现:
                          al /keyf  /delay
                 3.关闭签名的验证功能,因为程序集没有包含签名。
                    sn -Vr ShareDemo.dll
                 4.在发布之前,程序集可以用来实现重新签名:   
                     sn -R MyAssembly.dll mykey.snk
                     sn -Vu MyAssembly.dll

                 另一中理解方法:1,2两步相同 3.在生成程序集后,执行下面的命令以便后面可以将该程序集安装到GAC中,或者生成引用该程序集的其他程序集,以及测试该程序集。注意该操作只需执行一次,没有必要每次生成程序集时都执行一遍该命令。

                      SN -Vr MyAssembly.dll

                4.当准备打包和部署程序集时,取得公司的私有密钥,然后执行下面的命令:

                       SN -R MyAssembly.dll MyCompany.keys (这个文件包含了公钥和私钥)

               5. 执行下面的命令,恢复验证过程以进行测试:

                      SN  -Vu MyAssembly.dll

进行强命名程序集的全局部署的步骤:
        Gacutil /i  Sharedxxxx.dll
       
         强命名程序的引用
        在客户程序集中引用程序集的格式是:
             AssemblyRef #1
     ------------------------------------
                 Token: 0x230001
                 Public key or Token: b7 7a 5c 56 19 34 e0 89
                 Name: mscorlib
                 Major Version: 0x0001
                 Minor Version: 0x0000
                 Build  Number: 0x000ce4
                 Revision Number: 0x00000
                Locale: null
                HashValue  Blob: 23 23 f3 95 e3 73 0b 33
                Flags: [none](0000)
            
           编译时期:
             csc 将在以下目录中查找程序集:
                 1. 当前工作目录
                 2. 编译器目录使用的CLR所在的目录。
                 3. 任何用csc /lib命令行开关指定的目录。
                 4. 任何LIB环境变量中指定的目录。
            运行时期:
                 CLR如何解析类型引用:
                  1、同一个文件
                      对同一个文件中的类型的访问在编译时就确定了下来。CLR直接从该文件中加载被引用的类型。完成加载后,程序将继续执行。
                  2、不同的文件,相同的程序集(这里说的文件应该是模块文件或者直接是包含清单的模块文件,而不是源代码文件)
                     CLR首先确保被引用的文件在当前程序集清单中的FileDef表内。CLR然后回在加载程序集清单文件的目录中查找到被引用的文件。该文件被加载的同时,CLR会检查他的散列值以确保文件的完整性。
                 3、不同的文件,不同的程序集。
                 
                 具体搜索步骤见下图:
                      

                影响程序集搜索的方法有:
                1.应用程序的配置文件
                2.程序集的发布文件
                           AL /out: policy.1.0.xxx.dll /version:1.0.0.0  /keyfile:MyCompany.keys /linkresource:xxx.config
                           上面的命令就生成了一个包含发布者策略文件的程序集。
                            这个程序集需发布到GAC中。

 

   原文链接:http://edu.codepub.com/2010/0302/20624.php

posted on 2010-12-06 22:21  ringwang  阅读(255)  评论(0编辑  收藏  举报