介绍了
CIL
的基础知识之后,现在来研究
CIL
编程的实际使用,我们从正反向工程开始讨论。
正反向工程
大家已经知道可以使用 ildasm.exe 来查看由 C# 编译器生成的 CIL 代码(参见 .NET CIL系列第一篇:CIL介绍和入门 ),不过也许不知道 ildasm.exe 还允许将加载到 ildasm.exe 的程序集中的 CIL 都导出到一个外部文件中。一旦有了 CIL 代码,就可以使用 CIL 编译器 ilasm.exe 任意编辑或重新编译代码。
说明: reflector.exe 可以用于查看某个程序集的 CIL 代码,也可以把 CIL 代码翻译为接近的 C# 代码。然而如果程序集包含的 CIL 结构没有等价的 C# 实现( C# 和 VB 等只各自实现了 CIL 所有特性集的子集),我们只能使用 ildasm.exe 。
这个技术叫做正反向工程( round-trip-engineering ),在以下这些情况下它将很有用处。
n
需要修改一个没有源代码的程序集
n
正在使用的 .NET 语言编译器不够完美,产生了一些效率不足的 CIL 代码,而用户希望修改。
n
用户在构建可与 COM 互操作的程序集并且希望补充那些在转换过程中丢失的 IDL 特性,例如 COM 的 [helpstring] 特性。
为了解释正反向工程的过程,我们使用文本编辑器来创建一个新的 C# 代码文件( HelloProgram.cs ),并且定义下面的类(也可以使用 Visual Studio 2008 ,但要记得删除 AssemblyInfo.cs 这个文件来减少生成的 CIL 代码数量):
}
将这个文件保存到一个方便的位置(如 D:/HelloCilCode ) , 然后使用 csc.exe 编译:
csc /out:D:/HelloCilCode/HelloProgram.exe D:/HelloCilCode/HelloProgram.cs
现在开启 ildasm.exe 打开 HelloProgram.exe ,选择 File->Dump 菜单选项,将原始的 CIL 代码保存到一个新的 *il 文件( HelloProgram.il ),这个文件位于包含已编译程序集的文件夹中(结果对话框总的所有默认值都保持不变)。
说明:将程序集中的内容转储到文件时, ildasm.exe 会生成一个 *.res 文件。此时,我们刚才创建的 HelloProgram.cs 源代码文件和 HelloProgram.exe 文件已经可以忽略或删除了,因为我们不需要再用到它们了。
现在可以使用任意的文本编辑器打开这个 *.il 文件来查看 CIL 代码。结果如下(有少量的格式更改和注释):
正反向工程
大家已经知道可以使用 ildasm.exe 来查看由 C# 编译器生成的 CIL 代码(参见 .NET CIL系列第一篇:CIL介绍和入门 ),不过也许不知道 ildasm.exe 还允许将加载到 ildasm.exe 的程序集中的 CIL 都导出到一个外部文件中。一旦有了 CIL 代码,就可以使用 CIL 编译器 ilasm.exe 任意编辑或重新编译代码。
说明: reflector.exe 可以用于查看某个程序集的 CIL 代码,也可以把 CIL 代码翻译为接近的 C# 代码。然而如果程序集包含的 CIL 结构没有等价的 C# 实现( C# 和 VB 等只各自实现了 CIL 所有特性集的子集),我们只能使用 ildasm.exe 。
这个技术叫做正反向工程( round-trip-engineering ),在以下这些情况下它将很有用处。
n
需要修改一个没有源代码的程序集
n
正在使用的 .NET 语言编译器不够完美,产生了一些效率不足的 CIL 代码,而用户希望修改。
n
用户在构建可与 COM 互操作的程序集并且希望补充那些在转换过程中丢失的 IDL 特性,例如 COM 的 [helpstring] 特性。
为了解释正反向工程的过程,我们使用文本编辑器来创建一个新的 C# 代码文件( HelloProgram.cs ),并且定义下面的类(也可以使用 Visual Studio 2008 ,但要记得删除 AssemblyInfo.cs 这个文件来减少生成的 CIL 代码数量):
// 简单的C#控制台程序
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello CIL code!");
Console.ReadLine();
}
}
将这个文件保存到一个方便的位置(如 D:/HelloCilCode ) , 然后使用 csc.exe 编译:
csc /out:D:/HelloCilCode/HelloProgram.exe D:/HelloCilCode/HelloProgram.cs
现在开启 ildasm.exe 打开 HelloProgram.exe ,选择 File->Dump 菜单选项,将原始的 CIL 代码保存到一个新的 *il 文件( HelloProgram.il ),这个文件位于包含已编译程序集的文件夹中(结果对话框总的所有默认值都保持不变)。
说明:将程序集中的内容转储到文件时, ildasm.exe 会生成一个 *.res 文件。此时,我们刚才创建的 HelloProgram.cs 源代码文件和 HelloProgram.exe 文件已经可以忽略或删除了,因为我们不需要再用到它们了。
现在可以使用任意的文本编辑器打开这个 *.il 文件来查看 CIL 代码。结果如下(有少量的格式更改和注释):
//引用的程序集
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
.ver 2:0:0:0
}
//我们的程序集
.assembly HelloProgram
{
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module HelloProgram.exe
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003
.corflags 0x00000001
//