当我复制的DLL程序启动后,在运行时加载组件失败当我、组件、加载、程序

2023-09-03 16:30:37 作者:只弹琴卜谈情

在运行时我加载程序集与

At runtime I load an assembly with

Assembly assembly = Assembly.LoadFrom(@"c:\MyFolder\MyAssembly.dll");

这工作,如果装配的是文件夹中。

This works if the assembly is in that folder.

如果大会未在文件夹中我得到一个例外,当然告诉我,大会或它的一个依赖找不到。

If the assembly is NOT in the folder I get an exception of course telling me that the assembly or one of its dependencies could not be found.

我赶上了异常,并显示错误信息给用户。程序继续运行。

I'm catching the exception and display an error message to the user. The program keeps running.

如果我复制现在缺少的组件文件夹C:\ MyFolder的,而程序仍在运行,并触发功能,其中再次执行上面的我得到同样的异常的行 - 一个System.IO.FileNotFoundException - 再次,该组件找不到虽然DLL现在是在文件夹中。

If I copy now the missing assembly to the folder "c:\MyFolder" while the program is still running and trigger the function again which executes the line above I get the same exception - a System.IO.FileNotFoundException - again that the assembly could not be found although the DLL is now in the folder.

如果我重新启动它工作在应用程序和组件中。它也可以,如果我启动应用程序和DLL复制到该文件夹​​之前,我尝试加载组件后的第一次应用程序启动。

If I restart the application it works and the assembly is found. It also works if I start the application and copy the DLL to the folder before I try to load the assembly for the first time after application start.

所以,问题似乎涉及到的第一个失败的呼叫 Assembly.LoadFrom

So the problem seems to be related to the first failed call of Assembly.LoadFrom.

有什么可以为这种现象的原因,我能做些什么来解决这个问题?

What can be the reason for this behaviour and what can I do to solve the problem?

感谢您的帮助提前!

编辑:还有一个细节:

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

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

测试返回,但 Assembly.LoadFrom 抛出一个 FileNotFoundException异常

test returns true but Assembly.LoadFrom throws a FileNotFoundException.

推荐答案

功能,不是一个错误。这是一个DLL地狱应对措施。手术词是加载上下文,搜索苏珊娜·库克的博客,以更多地了解词组它。概括地说,CLR的记忆previous尝试加载程序集。首先,它会记录成功的绑定,并保证了的确切的相同的组件将被再次加载,即使磁盘内容发生了变化。可以毫无疑问,看到了好处,突然得到的另一个的组件,几乎都是灾难性的。

Feature, not a bug. It is a DLL Hell counter-measure. The operative term is 'loading context', search Suzanne Cook's blog for the phrase to learn more about it. In a nutshell, the CLR memorizes previous attempts to load an assembly. First and foremost, it records successful bindings and guarantees that the exact same assembly will be loaded again, even if the disk contents have changed. You can no doubt see the benefit of that, suddenly getting another assembly is almost always disastrous.

同样是如此的没有的程序集绑定。它会记住那些为好,出于同样的原因,它会辜负他们的未来。有没有文档化的方式来重新装载情况下,我知道了。 Assembly.LoadFile()加载组件没有加载上下文。但是,这会导致其他的一系列问题,你真的不想使用它。

The same is true for failed assembly binds. It memorizes those as well, for much the same reason, it will fail them in the future. There is no documented way to reset the loading context that I know of. Assembly.LoadFile() loads assemblies without a loading context. But that causes a whole range of other problems, you really don't want to use it.