I have an application which contains a number of plugins (MEF) which connect to a number of different I/O devices. Most of these plugins have a number of managed and unmanaged dlls.
One manufacturer has recently released new firmware and new drivers. The API remains the same.
I thought that I could include both dll versions in separate resource folders and copy the required set into the output folder when application starts up.
(I guess I could just make a second copy of the plugin and figure out a way of loading the correct one but I thought that copying the DLLs might be easier - especially considering that the plugin code is unchanged)
This does not work.
static MyClass() // static constructor
{
// required version?
if (envvar.Equals("4") )
{
path = "ver4.1.1";
}
else
{
path = "ver2.5.1";
}
// location of drivers
path = Path.Combine("./Prj/QX", path);
string[] files = Directory.GetFiles(path);
// Copy the files and overwrite destination files if they already exist.
foreach (string s in files)
{
string fileName = Path.GetFileName(s);
string destFile = Path.Combine(".", fileName);
File.Copy(s, destFile, true);
}
// force load of assemby
Assembly assy = LoadWithoutCache("driver.dll");
string fn = assy.FullName;
}
static 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);
}
}
The error message suggests that the original DLL was loaded or should have been loaded but could not be.
Could not load file or assembly 'driver, Version=1.5.77, Culture=neutral, PublicKeyToken=983247934' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Is there any way to achieve my goal or do I have to build 2 separate versions of my application?
EDIT I should also say that it is not necessary to have both DLLs loaded at the same time. It would be enough to start the application with a parameter which causes one or the other DLL to be loaded.
config. Under <runtime> , add a <codeBase> tag for each version of the DLL. This will resolve the runtime assembly loading conflict. That's it, now we can use both versions as we please.
Solution 1 DLL's are shared resources on the same machine and can be used by multiple process on the same machine.
One (complicated) way to achieve this is:
The FSW detects if an assembly gets changed or deleted.
Assemblies loaded into this context can only be examined! Make sure the assembly type implements the PluginInterface, by getting the types of an assembly and checking if the types implement your PluginInterface.
Because of the fact that you can only unload an AppDomain with all it's assemblies, you load each plugin assembly in its own AppDomain. This way the just unload the plugin's AppDomain.
Be sure to terminate all processes/threads of the plugin!
Shadow copying ensures the change of the original file by copying the assembly into a temporary path.
Put the path of a successfully loaded assembly into a list. This makes it easier to detect if an assembly needs to get loaded/reloaded.
Check which .dll was changed/deleted to unload the assembly, or if a new assembly was detected to load it.
Greetings, Blackanges
You could do it in several ways. One possibility would be to use the Managed Extensibility Framework (MEF). You could even monitor a folder where the dlls reside and load a new version as soon as a new one becomes available.
The other possibility is that you can use reflection to dynamically load the dll you want during runtime.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With