程序集文件重命名和Assembly.LoadFile

Fai*_*oor 5 c# clr file-io .net-assembly

所以情况如下:

我有一个名为Lib1.dll的程序集.出于某种原因(与问题无关)我不得不将程序集文件名重命名为Lib1New.dll,现在尝试使用Assembly.LoadFile加载重命名的程序集时,我注意到CLR也尝试加载Lib1.dll.

如果在搜索路径中找到Lib1.dll,它将被加载到地址空间中.无论是否找到Lib1.dll,该应用程序都能正常运行.(问题是如果发现Lib1.dll文件被锁定,其他进程无法删除).

在此输入图像描述

我不明白为什么LoadFile搜索并加载Lib1.dll.LoadFile应该在指定位置加载程序集文件的内容,为什么它在搜索文件.

LoadFile的MSDN文档:

使用LoadFile方法加载和检查具有相同标识但位于不同路径的程序集.LoadFile不会将文件加载到LoadFrom上下文中,也不会像LoadFrom方法那样使用加载路径解析依赖关系.LoadFile在这种有限的场景中很有用,因为LoadFrom不能用于加载具有相同标识但路径不同的程序集; 它只会加载第一个这样的组件.

Blu*_*kMN 2

我建议您尝试简化您的问题,因为我只是尝试重现您的情况并没有遇到任何问题。我创建了一个 Lib.dll 程序集,编译了它,创建了一个使用 LoadFile 加载它的控制台应用程序,然后将 Lib.dll 重命名为“LibNew.dll”,控制台对它的引用也更改为“LibNew.dll”。然后我重新编译 lib.dll 并运行控制台应用程序。当时我无法删除 LibNew.dll,但我能够删除 Lib.dll。

我怀疑您的 Lib.dll 可能在启动时从其自己的程序集中加载一些信息,并且在内部使用另一个 Load 函数来执行此操作,最终找到原始的 Lib.dll。但如果您有一个非常简单的 DLL,它就不会产生额外的负载。我的 DLL 有一个函数,我可以调用该函数,但我仍然看到上面报告的结果。这是我的代码:

控制台应用程序:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

库:

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

仅监视 LoadImage 调用,我发现它没有尝试加载 Lib.dll: LoadImage 调用的进程监视器跟踪

但是,通过监视所有事件,我发现它确实在应用程序目录中探测了 Lib.dll 进程监视器跟踪所有对 Debug\Lib 的引用

也许如果您将 DLL 放在另一个目录中,您可以强制执行您想要的行为?不过,考虑到文档,这是奇怪的行为。