Note that there are some explanatory texts on larger screens.

plurals
  1. POTrying to inject Elmah error logging using Mono.Cecil
    primarykey
    data
    text
    <p>I am using a third party assembly, which unfortunately swallows its exceptions, so I've decided to rewrite the assembly (fortunately it's not strongly typed) using Mono.Cecil (discovered this gem after some research in DI and AOP). I have tried to find as much information as possible but I still have some questions regarding the composition of the IL. </p> <p>I have already read <a href="https://stackoverflow.com/questions/11074518/add-a-try-catch-with-mono-cecil">this</a> and <a href="https://stackoverflow.com/questions/12769699/mono-cecil-injecting-try-finally">this</a>, so I get the idea of what I need to do, but like I said I'm not sure how to generate the right IL to make the call.</p> <p>I have used Cecil to extract the instructions from a method where I'm doing a simple try/catch -> log in Elmah -> let the exception carry on, which is what I need to inject.<br> This is the catch I'm trying to replicate:</p> <pre><code>catch (Exception ex) { Elmah.ErrorLog.GetDefault(System.Web.HttpContext.Current) .Log(new Elmah.Error(ex)); throw; } </code></pre> <p>These are the catch block instructions I obtained using Cecil:</p> <pre><code>IL_010d: stloc.s V_7 IL_010f: nop IL_0110: call System.Web.HttpContext System.Web.HttpContext::get_Current() IL_0115: call Elmah.ErrorLog Elmah.ErrorLog::GetDefault(System.Web.HttpContext) IL_011a: ldloc.s V_7 IL_011c: newobj System.Void Elmah.Error::.ctor(System.Exception) IL_0121: callvirt System.String Elmah.ErrorLog::Log(Elmah.Error) IL_0126: pop IL_0127: rethrow IL_0129: nop </code></pre> <p>I'm trying to replicate this block using Cecil and this is how far I have got:</p> <pre><code>var currentHttpContextInstruction = ilProcessor.Create(OpCodes.Call, module.Import(typeof(System.Web.HttpContext).GetProperty("Current").GetGetMethod())); var elmahGetDefaultInstruction = ilProcessor.Create(OpCodes.Call, module.Import(typeof(Elmah.ErrorLog).GetMethod("GetDefault"))); var instantiateElmahErrorInstruction = ilProcessor.Create(OpCodes.Newobj, module.Import(typeof(Elmah.Error).GetConstructor(new[] { typeof(System.Exception) }))); var elmahErrorLogInstruction = ilProcessor.Create(OpCodes.Callvirt, module.Import(typeof(Elmah.ErrorLog).GetMethod("Log"))); var rethrowInstruction = ilProcessor.Create(OpCodes.Rethrow); </code></pre> <p>What I am not so sure about is how to correctly replicate the remaining instructions...<br> Do I just create a <code>new VariableDefinition</code>, add it to <code>method.Body.Variables</code> and then do the <code>stloc</code> and <code>ldloc</code> operations on that variable? What about the <code>nop</code> and <code>pop</code> commands? Will I need to worry about <a href="https://stackoverflow.com/questions/7267480/does-mono-cecil-take-care-of-branches-etc-location">the issue raised in this question</a>?</p> <p>Any guidance on how to do this the right way would be greatly appreciated!</p> <p>Please note I've looked at the <a href="http://en.wikipedia.org/wiki/List_of_CIL_instructions" rel="nofollow noreferrer">meanings</a> of the commands, so my question is not about what they mean.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload