Reputation: 177153
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.
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.
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.
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?
Thank you for help in advance!
Edit: One more detail:
I've added a File.Exists
test:
string filename = @"c:\MyFolder\MyAssembly.dll";
bool test = File.Exists(filename);
Assembly assembly = Assembly.LoadFrom(filename);
test
returns true
but Assembly.LoadFrom
throws a FileNotFoundException
.
Upvotes: 8
Views: 2788
Reputation: 941942
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.
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.
Upvotes: 7
Reputation: 6159
In order to bypass the CLR caching of LoadFrom
attempts, you can change your code a little to use the Assembly.Load(byte[] rawAssembly)
overload.
Something like this:
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);
}
}
Upvotes: 5