Reputation: 405
I want to make a little sample code with Mono.Cecil The goal is to manipulate the IL. The method X does print something on the console. To test the manipulation of the IL code i remove all instructions from the method. But when I run External2.dll the Console Output is still printed (but the instructions to do the Console output are removed from the External2.dll). How can I fix this problem?
var module = ModuleDefinition.ReadModule("External.dll");
var types = module.Types;
foreach (var type in types) {
foreach (var method in type.Methods) {
if (method.Name == "X") {
Console.WriteLine(method.Body.Instructions.Count);
method.Body.Instructions.Clear();
Console.WriteLine(method.Body.Instructions.Count);
}
}
}
module.Write("External2.dll");
Upvotes: 1
Views: 824
Reputation: 4215
I think you need to use AssemblyDefinition
instead of ModuleDefinition
Also, you cannot simply remove all instructions from your method body. You need to have at least one ret
. For instance the code below does work:
using System;
using System.Linq;
using Mono.Cecil;
using System.IO;
namespace cecil
{
class Program
{
static void Main(string[] args)
{
X();
var assembly = AssemblyDefinition.ReadAssembly(typeof(Program).Assembly.Location);
var method = assembly.MainModule.Types.SelectMany(t => t.Methods).SingleOrDefault(m => m.Name == "X");
if (method == null)
{
System.Console.WriteLine("Method X not found.");
}
else
{
Console.WriteLine(method.Body.Instructions.Count);
method.Body.Instructions.Clear();
var ilProcessor = method.Body.GetILProcessor();
ilProcessor.Append(ilProcessor.Create(Mono.Cecil.Cil.OpCodes.Ret));
Console.WriteLine(method.Body.Instructions.Count);
var newAssemblyFileName= "External2.dll";
assembly.Write(newAssemblyFileName);
System.Console.WriteLine($"Assembly saved to {Path.GetFullPath(newAssemblyFileName)}");
}
}
private static void X()
{
System.Console.WriteLine("From X");
}
}
}
btw, you can always use https://cecilifier.me to help you out.
Upvotes: 2