Bon aperçu de la mise en œuvre try/catch dans Mono.Cecil was answered here, mais il s'arrête juste à court d'un essai complet/catch/enfin. Alors, comment implémentez-vous essayer/enfin en utilisant Mono.Cecil?Mono.Cecil: injection essayer/finalement?
Répondre
Voici comment injecter un final.
Vous devez d'abord corriger vos déclarations de retour. Vous n'en voulez qu'un.
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;
}
}
Ensuite, trouvez la première instruction. Vous devrez ignorer 2 s'il s'agit d'un constructeur d'instance.
Instruction FirstInstructionSkipCtor()
{
if (Method.IsConstructor && !Method.IsStatic)
{
return body.Instructions.Skip(2).First();
}
return body.Instructions.First();
}
point ensuite ensemble
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();
}
trouvé l'exemple vérifié très instructif et utile. J'ai rencontré un problème, cependant, dans des conditions plus complexes. Dans FixReturns(), à la fois les portées retournées void et non-void, la méthode de changement de ret -> laisse à travers la création de nouvelles instructions les orphelins les originaux. Cela peut laisser d'autres instructions avec l'orphelin en tant qu'opérande (par exemple, des branches à la ret originale). Le code résultant finit par être invalide.
Nous avons simplement mis à jour la paire d'opcode/opérande des instructions ret existantes par rapport à la création de nouvelles et tout semble bien.
Cheers.
- 1. Injection de GeneratedCodeAttribute avec Mono.Cecil
- 2. Mono.Cecil TypeRéférence à taper?
- 3. Mono.Cecil - code malicieux obfuscated
- 4. Mono.Cecil Liste Importation recenseur
- 5. Mono.Cecil créer de nouvelles instructions
- 6. Mono.Cecil convertir .exe en dll?
- 7. Remplacer une classe avec Mono.Cecil
- 8. Dll injection injection
- 9. paramètres génériques d'un ByReferenceType avec Mono.Cecil
- 10. Mono.Cecil: l'opération pourrait déstabiliser à l'exécution
- 11. Changer le type d'application avec Mono.Cecil?
- 12. CCI vs. Mono.Cecil - avantages et inconvénients
- 13. Mono.Cecil: ne peut pas voir classe enfant
- 14. Mono.Cecil - Comment obtenir des attributs personnalisés
- 15. injection
- 16. Injection de cohérence: injection d'objets partiellement initialisés
- 17. différence entre "Code Injection" et "Process Injection"?
- 18. mongoDB injection
- 19. injection Mysql
- 20. Javascript injection
- 21. Injection SQL
- 22. DataTable.Select injection
- 23. Mono.Cecil, Membre du compilateur manquant requis 'System.Runtime.CompilerServices.ExtensionAttribute..ctor'
- 24. Ajout d'un nouveau constructeur au type "existant" avec mono.cecil
- 25. Comment créer une méthode de remplacement à l'aide de Mono.Cecil?
- 26. Comment injecter un appel à System.Object.Equals avec Mono.Cecil?
- 27. Recherche d'assemblages de hiérarchie de types à l'aide de Mono.Cecil
- 28. Utilisez Mono.Cecil pour déterminer si un type implémente une interface
- 29. Injection de setter de ressort et injection de constructeur
- 30. Spring ProxyFactoryBean injection Problème
Donc, c'est fondamentalement le même processus que décrit dans ce post, en passant simplement ExceptionHandlerType.Finalement dans le nouveau ExceptionHandler(). Et si vous voulez essayer/catch/finally, vous créez deux instances "ExceptionHandler" et les ajoutez à la méthode, une pour le catch, une pour le finally. Si c'est le cas, les noms sont certainement déroutants puisque vous ne créez pas vraiment de nouveaux gestionnaires d'exceptions, au moins pour 'finally'. Merci pour les pointeurs. – naasking