Question

To re-produce the problem, I created such simple class, and this file will be compiled as "SourceDLL.dll".

namespace SourceDll
{
    public class Class1
    {
        static public int Add(int b, int c)
        {
            return b + c;
        }
    }
}

Then I use Mono.Cecil modify it, I just open and save it back.

namespace InstrumentSystemDll
{
    class Program
    {
        static void Main(string[] args)
        {
            var fileName = args[0];
            var assembly = AssemblyDefinition.ReadAssembly(string.Format(@"..\..\..\Dependences\{0}.dll", fileName));
            Console.WriteLine(string.Format(@"..\..\..\Dependences\{0}.Patched.dll", fileName));
            assembly.Write(string.Format(@"..\..\..\Dependences\{0}.Patched.dll", fileName));
        }
    }
}

I got a modified "SourceDll.Patched.dll" file, and then I try to use this file. Created a consloe app and reference the "SourceDll.Patched.dll".

namespace TestInstrumentDll
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(Class1.Add(1, 1));
        }
    }

}

Unfortunately, I got such error:

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or ass embly 'SourceDll, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified. at TestInstrumentDll.Program.Main(String[] args)

If I switched to original SourceDll.dll, it works and print a number "2" as we expected.

Was it helpful?

Solution

This is not something related to Mono.Cecil library. This is related to how the CLR will search for the assembly. The assembly name is written into the metadata of the assembly, and the CLR will look into the metadata to find the assembly. You can test it easily by just renaming your assembly from SourceDLL.dll to SourceDLL2.dll and then referencing to the renamed assebmly (Mono.Cecil is not involved!). You can see that you'll get the exact same exception.

To make it work, you need to change the assembly name before writing it:

var assembly = AssemblyDefinition.ReadAssembly(assemblyPath));
assembly.Name.Name += ".Patched";
assembly.Write(assemblyPath.Replace(".dll", ".Patched.dll"));
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top