C# 当我在程序启动后复制DLL时,在运行时加载程序集失败
在运行时,我用C# 当我在程序启动后复制DLL时,在运行时加载程序集失败,c#,.net,assemblies,C#,.net,Assemblies,在运行时,我用 Assembly assembly = Assembly.LoadFrom(@"c:\MyFolder\MyAssembly.dll"); 如果程序集位于该文件夹中,则此操作有效 如果程序集不在文件夹中,我当然会得到一个异常,告诉我程序集或其依赖项之一找不到 我正在捕获异常并向用户显示错误消息。程序一直在运行 如果我现在在程序仍在运行时将丢失的程序集复制到文件夹“c:\MyFolder”中,并再次触发执行上述行的函数,我会得到相同的异常-System.IO.FileNotFou
Assembly assembly = Assembly.LoadFrom(@"c:\MyFolder\MyAssembly.dll");
如果程序集位于该文件夹中,则此操作有效
如果程序集不在文件夹中,我当然会得到一个异常,告诉我程序集或其依赖项之一找不到
我正在捕获异常并向用户显示错误消息。程序一直在运行
如果我现在在程序仍在运行时将丢失的程序集复制到文件夹“c:\MyFolder”中,并再次触发执行上述行的函数,我会得到相同的异常-System.IO.FileNotFoundException-尽管DLL现在在文件夹中,但仍然找不到程序集
如果我重新启动应用程序,它就会工作,程序集就会被找到。如果我在应用程序启动后第一次尝试加载程序集之前启动应用程序并将DLL复制到文件夹中,它也会起作用
因此,问题似乎与第一次调用Assembly.LoadFrom
失败有关
这种行为的原因是什么?我能做些什么来解决问题
提前感谢您的帮助
编辑:另一个详细信息:
我添加了一个文件。存在测试:
string filename = @"c:\MyFolder\MyAssembly.dll";
bool test = File.Exists(filename);
Assembly assembly = Assembly.LoadFrom(filename);
test
返回true
但Assembly.LoadFrom
抛出一个FileNotFoundException
功能,而不是bug。这是一种反措施。操作术语是“加载上下文”,搜索短语以了解更多信息。简而言之,CLR会记住以前加载程序集的尝试。首先也是最重要的一点是,它记录成功的绑定,并保证即使磁盘内容已更改,也会再次加载完全相同的程序集。毫无疑问,您可以看到这样做的好处,突然获得另一个组件几乎总是灾难性的
失败的程序集绑定也是如此。它也会记住这些,出于同样的原因,它将来会让它们失败。据我所知,没有文档化的方法来重置加载上下文。Assembly.LoadFile()在没有加载上下文的情况下加载程序集。但这会导致一系列其他问题,您确实不想使用它。为了绕过LoadFrom
尝试的CLR缓存,您可以稍微更改代码以使用Assembly.Load(byte[]rawsembly)
重载
大概是这样的:
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);
}
}
是的,我很期待这不是一个bug,而是一些我不知道的CLR特性。问题:当我在我的主AppDomain
之外的另一个AppDomain
中加载失败的程序集,并在异常后卸载另一个AppDomain
时,新的程序集是否会尝试加载复制的程序集?是的,我认为加载上下文与AppDomain关联,但不是100%确定。AppDomainSetup.LoaderOptimization和ShadowCopyFiles属性使得给出明确的答案有点困难。事实上,当我卸载AppDomain、创建一个新的AppDomain并重试将程序集加载到新的AppDomain时,它会起作用。我刚刚对它进行了测试,但根据文档,这也加载了没有上下文的程序集,因此它应该与assembly.LoadFile()等效。