Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assembly file renaming and Assembly.LoadFile

So here is the situation:

I have an assembly called Lib1.dll. For some reason (not relevant to the question) I had to rename the assembly file name to Lib1New.dll, now while trying to load the renamed assembly using Assembly.LoadFile I noticed that the CLR tries to load the Lib1.dll as well.

If Lib1.dll is found in the search path it gets loaded in the address space. The application works fine irrespective of whether Lib1.dll was found or not. (The problem is that if Lib1.dll is found the file gets locked and can't be deleted by other processes).

enter image description here

I don't understand why the LoadFile searches and loads Lib1.dll. LoadFile is supposed to load the contents of an assembly file on the specified location, why is it searching for files.

MSDN documentation for LoadFile:

Use the LoadFile method to load and examine assemblies that have the same identity, but are located in different paths. LoadFile does not load files into the LoadFrom context, and does not resolve dependencies using the load path, as the LoadFrom method does. LoadFile is useful in this limited scenario because LoadFrom cannot be used to load assemblies that have the same identities but different paths; it will load only the first such assembly.

like image 803
Faisal Mansoor Avatar asked Oct 24 '22 14:10

Faisal Mansoor


2 Answers

I suggest you try a simplification of your problem because I just tried to reproduce your situation and encountered no problem. I created a Lib.dll assembly, compiled it, created a console application that loaded it with LoadFile, then renamed Lib.dll and the Console's reference to it to "LibNew.dll". Then I re-compiled lib.dll and ran the console application. At that point I was unable to delete LibNew.dll, but I was able to delete Lib.dll.

I suspect your Lib.dll may possibly be loading some information from its own assembly as it starts up, and is internally using another Load function to do so, which ends up finding the original Lib.dll. But if you have a very simple DLL, it wouldn't do that extra load. My DLL has a function, which I was able to call, but I still saw my reported results above. Here's my code:

Console Application:

class Program
{
    static void Main(string[] args)
    {
        System.Reflection.Assembly assy = System.Reflection.Assembly.LoadFile(args[0]);
        Type class1 = assy.GetType("Lib.Class1");

        System.Reflection.MethodInfo myMethod = class1.GetMethod("MyMethod");
        Console.WriteLine(myMethod.Invoke(null, new object[] {"This is a string"}).ToString());

        Console.ReadLine();
    }
}

Lib:

namespace Lib
{
public class Class1
{
    public static string MyMethod(string param)
    {
        return "Fixed: [" + param.Replace(" ", "-") + "]";
    }
}
}

Monitoring just LoadImage calls, I see that it did not try to load Lib.dll: Process Monitor Trace of LoadImage calls

However, monitoring all events, I see that it did probe for Lib.dll in the application directory. Process Monitor Trace of all references to Debug\Lib

Perhaps if you put the DLL in another directory you can force the behavior you want? It is strange behavior, though, considering the documentation.

like image 116
BlueMonkMN Avatar answered Oct 29 '22 20:10

BlueMonkMN


LoadFile uses Windows file searching and not the .NET's assembly resolution. But it still searches for the file.

It is similar to calling new FileStream() where you can pass a fileName and it will look for it in PATH, etc if it is a relative path.

like image 42
Aliostad Avatar answered Oct 29 '22 21:10

Aliostad