第 2 章 生成、打包、部署和管理应用程序及类型
第 2 章 生成、打包、部署和管理应用程序及类型
NyxX第 2 章 生成、打包、部署和管理应用程序及类型
本章内容:
2.1 .NET Framework 部署目标
多年来,Windows因为不稳定和过于复杂而一直受到口碑不佳的影响。有几个原因导致了这种状况。
- 第一,所有应用程序都使用来自Microsoft或其他厂商的动态链接库(DLL),这使得代码的开发者无法百分之百确定其他人将如何使用该代码。
- 第二,安装过程复杂,影响到系统的各个组件,导致备份和移动应用程序困难。
- 第三,安装应用程序可能引入来自不同公司的文件,甚至无意中安装恶意代码。
.NET Framework尝试解决这些问题。它解决了DLL hell的问题,减少了应用程序的分散性,并通过代码访问安全性模型提供了更多的安全性控制。
2.2 将类型生成到模块中
响应文件
响应文件是一种包含编译器命令行开关的文本文件。通过在命令行中指定响应文件的名称,可以告诉编译器使用其中的开关。
由于全局CSC.rsp文件引用了所有列出的程序集,因此不需要使用C#编译器的/reference开关来显示引用这些程序集。
2.3 元数据概述
CLR头是需要CLR的托管模块特有的信息块,包括CLR版本号、标志、模块入口方法等。最后,CLR头还包含了一些元数据表的大小和偏移量。
元数据是有几个表构成的二级制数据块。有三种表,分别是定义表(definition table)、引用表(reference table)和清单表(manifest table)。
表 2-1 常用的数据定义表
| 元数据定义表名称 | 说明 |
|---|---|
| ModuleDef | 总是包含对模块进行标识的一个记录项。该记录项包含模块文件名和扩展名(不含路径),以及模块版本ID(形式为编译器创建的GUID)。这样可在保留原始名称记录的前提下自由重命名文件。但强烈反对重命名文件,因为可能妨碍 CLR 在运行时正确定位程序集 |
| TypeDef | 模块定义的每个类型在这个表中都有一个记录项。每个记录项都包含类型的名称、基类型、一些标志(public,private等)以及一些索引,这些索引指向 MethodDef 表中该类型的方法、FieldDef 表中该类型的字段、PropertyDef 表中该类型的属性以及 EventDef 表中该类型的事件 |
| MethodDef | 模块定义的每个方法在这个表中都有一个记录项。每个记录项都包含方法的名称、一些标志(private,public,virtual,abstract,static,final 等)、签名以及方法的 IL 代码在模块中的偏移量。每个记录项还引用了 ParamDef 表中的一个记录项,后者包括与方法参数有关的更多信息 |
| FieldDef | 模块定义的每个字段在这个表中都有一个记录项。每个记录项都包含标志(private,public等)、类型和名称 |
| ParamDef | 模块定义的每个参数在这个表中都有一个记录项。每个记录项都包含标志(in,out,retval 等)、类型和名称 |
| EventDef | 模块定义的每个事件在这个表中都有一个记录项。每个记录项都包含标志和名称 |
表 2-2 常用的引用元数据表
| 引用元数据表名称 | 说明 |
|---|---|
| AssemblyRef | 模块引用的每个程序集在这个表中都有一个记录项。每个记录项都包含绑定该程序集所需的信息:程序集名称(不含路径和扩展名)、版本号、语言文化(culture)以及公钥 token(根据发布者的公钥生成的一个小的哈希值,标识了所引用程序集的发布者)。每个记录项还包含一些标志(flag)和一个哈希值。 |
| ModuleRef | 实现该模块所引用的类型的每个 PE 模块在这个表中都有一个记录项。每个记录项都包含模块的文件名和扩展名(不含路径)。可能是别的模块实现了你需要的类型,这个表的作用便是建立同那些类型的绑定关系 |
| TypeRef | 模块引用的每个类型在这个表中都有一个记录项。每个记录项都包含类型的名称和一个引用(指向类型的位置)。如果类型在另一个类型中实现,引用指向一个 TypeRef 记录项。如果类型在同一个模块中实现,引用指向一个 ModuleDef 记录项。如果类型在调用程序集内的另一个模块中实现,引用指向一个 ModuleRef 记录项。如果类型在不同的程序集中实现,引用指向一个 AssemblyRef 记录项 |
| MemberRef | 模块引用的每个成员(字段和方法,以及属性方法和事件方法)在这个表中都有一个记录项。每个记录项都包含成员的名称和签名,并指向对成员进行定义的那个类型的 TypeRef 记录项 |
2.4 将模块合并成程序集
清单(manifest)
清单也是一个元数据表集合,表中主要包含作为程序组成部分的那些文件的名称。此外,还描述了程序集的版本、语言文化、发布者、公开导出的类型以及构成程序集的所有文件。
表 2-3 清单元数据表
| 清单元数据表名称 | 说明 |
|---|---|
| AssemblyDef | 如果模块标识的是程序集,这个元数据表就包含单一记录项来列出程序集名称(不含路径和扩展名)、版本(major,minor,build 和 reversion)、语言文化(culture)、一些标志(flag)、哈希算法以及发布者公钥(可为 null) |
| FileDef | 作为程序集一部分的每个 PE 文件和资源文件在这个表中都有一个记录项(清单本身所在的文件除外,该文件在 AssemblyDef 表的单一记录中列出)。在每个记录项中,都包含文件名和扩展名(不含路径)、哈希值和一些标志(flags)。如果程序集只包含它自己的文件,FileDef表将无记录 |
| ManifestResourceDef | 作为程序集一部分的每个资源在这个表中都有一个记录项。记录项中包含资源名称、一些标志(如果在程序集外部可见,就为 public;否则为 private)以及 FileDef 表的一个索引(指出资源或流包含在哪个文件中)。如果资源不是独立文件(比如.jpg 或者 .gif 文件),那么资源就是包含在 PE 文件中的流。对于嵌入资源,记录项还包含一个偏移量,指出资源流在 PE 文件中的起始位置 |
| ExportedTypesDef | 从程序集的所有 PE 模块中导出的每个 public 类型在这个表中都有一个记录项。记录项中包含类型名称、FileDef 表的一个索引(指出类型由程序集的哪个文件实现)以及 TypeDef 表的一个索引。注意,为节省空间,从清单所在文件导出的类型不再重复,因为可通过元数据的 TypeDef 表获取类型信息 |





