Adding exception handlers with Mono.Cecil is not difficult, it just requires you to know how exception handlers are laid out in the metadata.

Let say you have the C# method:

static void Throw ()
{
throw new Exception ("oups");
}

If you decompile it, it should look somewhat similar to this:

.method private static hidebysig default void Throw ()  cil managed
{
IL_0000: ldstr "oups"
IL_0005: newobj instance void class [mscorlib]System.Exception::.ctor(string)
IL_000a: throw
}

Now let say that you want to inject code in this method such as it's similar to the C# code:

static void Throw ()
{
try {
throw new Exception ("oups");
} catch (Exception e) {
Console.WriteLine (e);
}
}

That is, you simply want to wrap the existing code in a try catch handler. You can do it easily with Cecil this way:

    var method = ...;
var il = method.Body.GetILProcessor (); var write = il.Create (
OpCodes.Call,
module.Import (typeof (Console).GetMethod ("WriteLine", new [] { typeof (object)})));
var ret = il.Create (OpCodes.Ret);
var leave = il.Create (OpCodes.Leave, ret); il.InsertAfter (
method.Body.Instructions.Last (),
write); il.InsertAfter (write, leave);
il.InsertAfter (leave, ret); var handler = new ExceptionHandler (ExceptionHandlerType.Catch) {
TryStart = method.Body.Instructions.First (),
TryEnd = write,
HandlerStart = write,
HandlerEnd = ret,
CatchType = module.Import (typeof (Exception)),
}; method.Body.ExceptionHandlers.Add (handler);

This code is manipulating the previous method to look like this:

.method private static hidebysig default void Throw ()  cil managed
{
.maxstack 1
.try { // 0
IL_0000: ldstr "oups"
IL_0005: newobj instance void class [mscorlib]System.Exception::'.ctor'(string)
IL_000a: throw
} // end .try 0
catch class [mscorlib]System.Exception { // 0
IL_000b: call void class [mscorlib]System.Console::WriteLine(object)
IL_0010: leave IL_0015
} // end handler 0
IL_0015: ret
}

We're adding three new instructions: a call to Console.WriteLine, a leave to gracefully exit the catch handler, and finally (pun intended), a ret. Then we're simply creating a ExceptionHandler instance to represent a try catch handler whose try encompasses the existing body, and whose catch is the WriteLine statement.

One important thing to note is that the end instruction of a range is not contained inside the range. It's basically a [TryStart:TryEnd[ range.

Add a try-catch with Mono Cecil的更多相关文章

  1. 运用Mono.Cecil 反射读取.NET程序集元数据

    CLR自带的反射机智和API可以很轻松的读取.NET程序集信息,但是不能对程序集进行修改.CLR提供的是只读的API,但是开源项目Mono.Cecil不仅仅可以读取.NET程序集的元数据,还可以进行修 ...

  2. 基于Mono.Cecil的静态注入

    Aop注入有2种方式:动态注入和静态注入,其中动态注入有很多实现了 动态注入有几种方式: 利用Remoting的ContextBoundObject或MarshalByRefObject. 动态代理( ...

  3. 使用Mono Cecil 动态获取运行时数据 (Atribute形式 进行注入 用于写Log) [此文报考 xxx is declared in another module and needs to be imported的解决方法]-摘自网络

    目录 一:普通写法 二:注入定义 三:Weave函数 四:参数构造 五:业务编写 六:注入调用 7.  怎么调用别的程序集的方法示例 8. [is declared in another module ...

  4. 巧用Mono.Cecil反射加载类型和方法信息

    最近在做服务的细粒度治理,统一管理所有服务的方法.参数.返回值信息.方便后续的各个模块之间的对接和协作. 目前系统中所有的服务,管理到接口契约粒度,即服务接口声明和服务接口实现.要做服务的细粒度治理: ...

  5. Mono.Cecil - 0.6

    原文:Mono.Cecil - 0.6 项目地址:Mono.Cecil 项目描述:In simple English, with Cecil, you can load existing manage ...

  6. c# Mono.Cecil IL方式 读MethodBody

    using Kufen.Common.Definitions; using Mono.Cecil; using System; using System.Collections.Generic; us ...

  7. Mono.Cecil 初探(一):实现AOP

    序言 本篇文章介绍基于Mono.Cecil实现静态AOP的两种方式:无交互AOP和交互式AOP. 概念介绍 Mono.Cecil:一个可加载并浏览现有程序集并进行动态修改并保存的.NET框架. AOP ...

  8. C# Asp.net中的AOP框架 Microsoft.CCI, Mono.Cecil, Typemock Open-AOP API, PostSharp -摘自网络 (可以利用反射 Attribute 进行面向切面编程 可以用在记录整个方法的Log方面)

    Both Microsoft.CCI and Mono.Cecil are low-level, and don't validate produced assemblies. It takes lo ...

  9. 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)

    原文 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习) Mono.Cecil是一个强大的MSIL的注入工具,利用它可以实现动态创建程序集,也可以实现拦截器横向切入动态方法,甚至还 ...

随机推荐

  1. MVC教程三:URL匹配

    1.使用{parameter}做模糊匹配 {parameter}:花括弧加任意长度的字符串,字符串不能定义成controller和action字母.默认的就是模糊匹配. 例如:{admin}. usi ...

  2. KBEngine.executeRawDatabaseCommand使用

    先贴一段官方的API介绍: def executeRawDatabaseCommand( command, callback, threadID, dbInterfaceName ): 功能说明: 这 ...

  3. HTTP协议详解(文档)

    目录引言................................................................................................ ...

  4. 关于Cocos2d-x中字体的使用

    1.如果使用的是系统自带的 static Label* createWithSystemFont ( const std::string & text,        const std::s ...

  5. 【F12】修改 DevTools的主题

    1.点击setting

  6. tensorflow中slim模块api介绍

    tensorflow中slim模块api介绍 翻译 2017年08月29日 20:13:35   http://blog.csdn.net/guvcolie/article/details/77686 ...

  7. android ContentProvider 笔记

    学习android的contentprovider.笔记记录于此. contentprovider作用是将数据共享给其他的应用. 参考链接 https://www.tutorialspoint.com ...

  8. 如果不得已需要全局变量,则使全局变量加前缀 g_(表示 global)

    如果不得已需要全局变量,则使全局变量加前缀 g_(表示 global). 例如: int g_howManyPeople; // 全局变量 int g_howMuchMoney; // 全局变量 #i ...

  9. if、for、while、do 等语句自占一行

    if.for.while.do 等语句自占一行,执行语句不得紧跟其后.不论 执行语句有多少都要加{}.这样可以防止书写失误. #include <iostream> /* run this ...

  10. ThinkPHP Mongo驱动update方法支持upsert参数

    Mongo数据库update操作有一个相对于Mysql的关键特性,它可以使用upsert模式,当更新的数据不存在时,直接插入,但是ThinkPHP的Mongo驱动居然不支持这一特性,没办法,自力更生了 ...