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. centsos7修改主机名 [root@st152 ~]# cat /etc/hostname

    CentOS7修改服务器主机名方法CentOS7下修改主机名第一种:hostname 主机名01.hostname 主机名称 <pre name="code" class=& ...

  2. 修改jdk

    (一)修改jdk的path: (二)修改eclipse里面的jre环境 (三)修改具体项目的jre环境 build path -> config build path (四)修改服务运行环境

  3. 用 CSS 实现打印显示底色

    上一篇有讲到如何在浏览器端实现打印功能.后面发现有个问题,就是表格表头有背景颜色,但是实际打印出来无背景颜色.网上的方法主要有以下几种实现方式: 1.把背景颜色写成行内样式,如下图所示: 但是发现这样 ...

  4. 7 款基于 JavaScript/AJAX 的文件上传插件

    本文整理了7款基于JavaScript和AJAX的文件上传插件,这些插件基本上都能实现以下功能: 多文件上传 拖拽操作 实时上传进度 自定义上传限制 希望能为你的开发工作带来帮助. 1.  jQuer ...

  5. 数据库之“on”“where”区别

    数据库在通过连接两张或者多张表返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户 在使用inner join(内连接)没有区别,但是 在使用left jion时,on和where条件的 ...

  6. REFLECTOR和FILEDISASSEMBLER的下载与使用

    .NET Reflector 下载地址 http://www.aisto.com/roeder/dotnet FileDisassembler 下载地址 http://www.denisbauer.c ...

  7. 视差滚动(Parallax Scrolling)插件补充

    13. Windows Windows (github) 是一个让你用占据整个屏幕的section来构建单面网站的插件.该插件提供给你一些回调函数,当新的section出现在可视区并且并且处理快照时被 ...

  8. Mysql中Innodb大量插入数据时SQL语句的优化

    innodb优化后,29小时入库1300万条数据 参考:http://blog.51yip.com/mysql/1369.html 对于Myisam类型的表,可以通过以下方式快速的导入大量的数据: A ...

  9. 接口日志记录AOP实现-LogAspect

    使用spring aop日志记录 所需jar包 pom.xml <!-- logger begin --> <dependency> <groupId>org.sl ...

  10. Linux内核剖析 之 内存管理

    1. 内存管理区 为什么分成不同的内存管理区? ISA总线的DMA处理器有严格的限制:仅仅能对物理内存前16M寻址. 内核线性地址空间仅仅有1G,CPU不能直接訪问全部的物理内存. ZONE_DMA  ...