Mono. Cecil-1, 0.6

Source: Internet
Author: User
Project address: Mono. Cecil
Project Description: In simple English, with Cecil, you can load existing managed assemblies, browse all the contained types, modify them on the fly and save back to the disk the modified assembly.
Similar projects: Microsoft CCI
Common Compiler Infrastructure: Metadata API
Common Compiler Infrastructure: Code Model and AST API
Common Compiler Infrastructure: Sample applications
Common Compiler Infrastructure-Contrib
Comparison: From StackOverflow
Mono. cecil has better, more understandable and easy in use object model. however, I had an uugly bug when used it in my program (reference to the wrong method was saved in the assembly; I think there was some bug with metadata tokens handling)
Microsoft. CCI has an uugly, utterly over-designed object model in the same time lacking implements simple features; however, it's more mature than Mono. cecil. finally, I abandoned Mono. cecil and used Microsoft. CCI for my program.

Basic example
Cecil is to operate the compiled IL assembly, so first write a simple Console exe Program, here the project name uses Cecil. Program:

using System;using System.Reflection;namespace Cecil.Program{    class Program    {        static void Main(string[] args)        {            TestType tt = new TestType();            tt.SayHello();            tt.AboutMe();            Console.ReadKey();        }    }    public class TestType    {        [Obsolete]        public void SayHello()        {            Console.WriteLine("\tHello Cecil !");        }        public void AboutMe()        {            Type type = typeof(TestType);            MethodInfo method = type.GetMethod("SayHello");            if (method.IsVirtual)                Console.WriteLine("\tI'm a virtual method");            else                Console.WriteLine("\tI'm a non-virtual method");            object[] attributes = method.GetCustomAttributes(false);            if (attributes != null && attributes.Length > 0)            {                Console.WriteLine("\tI have the following attributes:");                foreach (object attr in attributes)                    Console.WriteLine("\t\t" + attr.GetType().Name);            }        }    }}

The running result of this Assembly is as follows:

The code for the method SayHello IL is as follows:

Next, use another Console exeprogram to modify cecil.program.exe. The project name uses Cecil:

Using Mono. cecil; using Mono. cecil. pencil; AssemblyDefinition assembly = AssemblyFactory. getAssembly ("Cecil.Program.exe"); TypeDefinition type = assembly. mainModule. types ["Cecil. program. testType "]; MethodDefinition sayHello = null; foreach (MethodDefinition md in type. methods) if (md. name = "SayHello") sayHello = md; // Console. writeLine (string value) method MethodInfo writeLine = typeof (Console ). getMethod ("Write Line ", new Type [] {typeof (string)}); // Console. the WriteLine method imports the MainModule and returns the reference method MethodReference writeLineRef = assembly in AssemblyDefinition. mainModule. import (writeLine); // insert a trace statement at the beginning of the SayHello method // Console. writeLine ("> Intercepting"); // If the inserted statement requires a function input parameter, it must be inserted in OpCodes. after commands such as Ldarg, CilWorker worker = sayHello. body. cilWorker; Instruction ldstr = worker. create (OpCodes. ldstr, "> Intercepting" + sayHello. Name); Instruction call = worker. create (OpCodes. call, writeLineRef); Instruction first = sayHello. body. instructions [0]; worker. insertBefore (first, call); worker. insertBefore (call, ldstr); // insert a trace statement at the end of the SayHello method // Console. writeLine ("> Intercepted"); // The statement must be inserted in OpCodes. int offset = sayHello. body. instructions. count-1; Instruction last = sayHello. body. instructions [offset --]; while (last. opCode = OpCodes. nop | last. opCode = OpCodes. ret) last = sayHello. body. instructions [offset --]; ldstr = worker. create (OpCodes. ldstr, "> Intercepted" + sayHello. name); worker. insertAfter (last, ldstr); worker. insertAfter (ldstr, call); // change the SayHello Method to the virtual method sayHello. isVirtual = true; // Add a SerializableAttributeCustomAttribute attribute = new CustomAttribute (assembly. mainModule. import (typeof (Serializ AbleAttribute ). getConstructor (Type. emptyTypes); sayHello. customAttributes. add (attribute); AssemblyFactory. saveAssembly (assembly, "Cecil.Program.modified.exe"); Console. writeLine ("Assembly modified successfully! "); Console. ReadKey ();

The explain result is as follows:

The modified method SayHello's IL code is as follows:

From the basic usage, we can see that Cecil is indeed easy to use and the object model structure is very practical. Here is a main object structure diagram of the official website:

Complexity of IL commands
It is very easy to modify the assembly at the assembly, type, and method levels. However, if you want to modify the IL code of the method body, you may encounter some troubles, requires careful processing
For example, if the preceding SayHello method is like this:

public void SayHello(bool print){    if (print)        Console.WriteLine("\tHello Cecil !");}

The test code is called as follows:

TestType2 tt2 = new TestType2();tt2.SayHello(true);tt2.SayHello(false);Console.ReadKey();

The running result only outputs a Hello Cecil! In the message, you still use cecil.exe to modify the Assembly. The running result is as follows:

When you call tt2.SayHello (false);, there should also be a> Intercepted SayHello message, but there is no output. Compare with the IL code:

The modified IL code is as follows:

If the value of IL_000b is false, the returned command IL_0021 will be directly redirected and no Intercepted message will be output.

You can use Mono. Cecil to modify the jump address. For example:

// Obtain the command brfalse. sInstruction jmp = sayHello. Body. Instructions [1];... // change the target address to the IL_0017 ldstr command location jmp. Operand = ldstr;

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.