在程序启动后复制DLL时,在运行时加载程序集失败

Sla*_*uma 8 .net c# assemblies

在运行时我加载一个程序集

Assembly assembly = Assembly.LoadFrom(@"c:\MyFolder\MyAssembly.dll");
Run Code Online (Sandbox Code Playgroud)

如果程序集位于该文件夹中,则此方法有效.

如果程序集不在文件夹中,我会得到一个例外,当然告诉我无法找到程序集或其中一个依赖项.

我正在捕获异常并向用户显示错误消息.该程序继续运行.

如果我现在将缺少的程序集复制到文件夹"c:\ MyFolder",同时程序仍在运行并再次触发执行上述行的函数,我得到相同的异常 - 一个System.IO.FileNotFoundException - 再次表示程序集可以虽然DLL现在在文件夹中,但是找不到.

如果我重新启动应用程序,它就可以运行并找到程序集.如果我在应用程序启动后第一次尝试加载程序集之前启动应用程序并将DLL复制到该文件夹​​,它也可以工作.

所以问题似乎与第一次失败的呼叫有关Assembly.LoadFrom.

这种行为可能是什么原因,我该怎么做才能解决问题?

提前感谢您的帮助!

编辑:还有一个细节:

我添加了一个File.Exists测试:

string filename = @"c:\MyFolder\MyAssembly.dll";
bool test = File.Exists(filename);
Assembly assembly = Assembly.LoadFrom(filename);
Run Code Online (Sandbox Code Playgroud)

test返回,trueAssembly.LoadFrom抛出一个FileNotFoundException.

Han*_*ant 7

功能,而不是错误.这是一个DLL地狱反措施.操作术语是"加载上下文",在Suzanne Cook的博客中搜索关于它的更多信息.简而言之,CLR记忆了以前加载装配的尝试.首先,它记录成功的绑定,保证了精确的相同的组件将被再次加载,即使磁盘内容发生了变化.你无疑可以看到它的好处,突然得到另一个集会几乎总是灾难性的.

失败的装配绑定也是如此.它也记住了这些,出于同样的原因,它将来会失败.没有记录的方法来重置我所知道的加载上下文.Assembly.LoadFile()加载没有加载上下文的程序集.但这会导致一系列其他问题,你真的不想使用它.


Ran*_*Ran 5

为了绕过CLR缓存LoadFrom尝试,您可以稍微更改代码以使用Assembly.Load(byte[] rawAssembly)重载.

像这样的东西:

Assembly LoadWithoutCache(string path)
{
    using (var fs = new FileStream(path, FileMode.Open))
    {
        var rawAssembly = new byte[fs.Length];
        fs.Read(rawAssembly, 0, rawAssembly.Length);
        return Assembly.Load(rawAssembly);
    }
}
Run Code Online (Sandbox Code Playgroud)