在Mono.Cecil was answered here中實現try/catch的好概述,但他停止了一個完整的try/catch/finally。那麼你怎麼實現/最終使用Mono.Cecil?Mono.Cecil:注入try/finally?
3
A
回答
8
下面是如何注入最後。
首先你需要修復你的返回語句。你只需要一個。
Instruction FixReturns()
{
if (Method.ReturnType == TypeSystem.Void)
{
var instructions = body.Instructions;
var lastRet = Instruction.Create(OpCodes.Ret);
instructions.Add(lastRet);
for (var index = 0; index < instructions.Count - 1; index++)
{
var instruction = instructions[index];
if (instruction.OpCode == OpCodes.Ret)
{
instructions[index] = Instruction.Create(OpCodes.Leave, lastRet);
}
}
return lastRet;
}
else
{
var instructions = body.Instructions;
var returnVariable = new VariableDefinition("methodTimerReturn", Method.ReturnType);
body.Variables.Add(returnVariable);
var lastLd = Instruction.Create(OpCodes.Ldloc, returnVariable);
instructions.Add(lastLd);
instructions.Add(Instruction.Create(OpCodes.Ret));
for (var index = 0; index < instructions.Count - 2; index++)
{
var instruction = instructions[index];
if (instruction.OpCode == OpCodes.Ret)
{
instructions[index] = Instruction.Create(OpCodes.Leave, lastLd);
instructions.Insert(index, Instruction.Create(OpCodes.Stloc, returnVariable));
index++;
}
}
return lastLd;
}
}
然後找到第一條指令。如果它是一個實例構造函數,則需要跳過2。
Instruction FirstInstructionSkipCtor()
{
if (Method.IsConstructor && !Method.IsStatic)
{
return body.Instructions.Skip(2).First();
}
return body.Instructions.First();
}
然後縫合它一起
void InnerProcess()
{
body = Method.Body;
body.SimplifyMacros();
ilProcessor = body.GetILProcessor();
var returnInstruction = FixReturns();
var firstInstruction = FirstInstructionSkipCtor();
var beforeReturn = Instruction.Create(OpCodes.Nop);
ilProcessor.InsertBefore(returnInstruction, beforeReturn);
InjectIlForFinaly(returnInstruction);
var handler = new ExceptionHandler(ExceptionHandlerType.Finally)
{
TryStart = firstInstruction,
TryEnd = beforeReturn,
HandlerStart = beforeReturn,
HandlerEnd = returnInstruction,
};
body.ExceptionHandlers.Add(handler);
body.InitLocals = true;
body.OptimizeMacros();
}
1
實測值所檢查的例子相當的信息和是有用的。雖然在更復雜的條件下遇到了問題。在FixReturns()中,無論是無效的還是無效的返回範圍,更改ret的方法 - >通過創建新的指令孤立原來的方法。這可以將其他指令與孤兒作爲操作數(例如,分支到原始ret)。最終的代碼最終會失效。
我們只是簡單地更新了現有的ret指令的操作碼/操作數對與創建新操作碼對,並且都顯得很好。
乾杯。
相關問題
- 1. 使用Mono.Cecil注入方法?
- 2. 如何使用Mono.Cecil向System.Object.Equals注入調用?
- 3. Mono.Cecil能導入列表枚舉
- 4. Mono.Cecil GetTypeReference to ICommand
- 5. 檢查Mono.Cecil和Mono.Cecil.Cil
- 6. Mono.Cecil type.IsAssignableFrom(derivedType)等效
- 7. Mono.Cecil convert .exe to dll?
- 8. Mono.Cecil類似於Type.GetInterfaceMap?
- 9. Mono.Cecil類型引用類型?
- 10. 用Mono.Cecil代替班級
- 11. Mono.Cecil - 錯誤的mscorlib版本
- 12. Mono.Cecil能:登錄方法的進入和退出點
- 13. Mono.Cecil能寫庫目標框架3.5 - 寫入參考MSCORLIB 4.0
- 14. 注入被注入類
- 15. 注入值將被注入
- 16. Mono.Cecil - 混淆的惡意代碼
- 17. Mono.Cecil引用C#中的以下結構?
- 18. Mono.Cecil會照顧樹枝等位置嗎?
- 19. 使用mono.cecil添加自定義屬性?
- 20. Instruction.Offset在mono.cecil中代表什麼?
- 21. Mono.Cecil - 如何獲得自定義屬性
- 22. 如何使用Mono.Cecil/dnlib編輯AssemblyInfo?
- 23. 如何在Mono.Cecil中創建Ldarg_S指令?
- 24. CCI與Mono.Cecil - 優點和缺點
- 25. 如何使用Mono.Cecil創建HelloWorld.exe
- 26. 用Mono.Cecil提取方法調用參數
- 27. Fody/Mono.Cecil:在調試器中隱藏行
- 28. Mono.Cecil能:操作可以在運行時
- 29. 混淆 - 重命名變量與mono.cecil
- 30. 使用依賴注入來注入依賴注入器
因此,它基本上與該文章中描述的過程相同,只是將ExceptionHandlerType.Finally傳遞到新的ExceptionHandler()中。如果你想要try/catch/finally,你需要創建兩個「ExceptionHandler」實例並將它們添加到方法中,一個用於catch,一個用於finally。如果是這樣的話,那麼這些名字肯定會讓人困惑,因爲你並沒有真正創建新的異常處理程序,至少對於'finally'來說。感謝指針。 – naasking