This is a follow-up to a previous question Is it possible to switch DLLs at runtime so as to use a different version?.
Since posting that question I have reorganised my project but am still have DLL loading problems.
I have 3 main projects: the application, a library containing MEF plugins and a second library containing more MEF plugins. Each plugin handles a type of IO device.
The manufacturer of one of the devices has produced a new set of identically named but incompatible DLLs. I now have 2 plugins to handle each version and put them in 2 separate projects (MEF Lib1 & MEF Lib2).
The MEF loader decides which one of the conflicting plugins to load (only one is needed) and the plugin is told to initialise itself. It then copies its' DLLs (managed and unmanaged) to the execution folder before the DLLs are accessed.
This does not work as desired. The managed DLLs are correct but the unmanaged DLL that actually gets loaded is an older version.
I have tried using the AppDomain.AssemblyResolve event but this only seems to be activated when a DLL cannot be found. In my case, the DLL is always found - just not the one I want.
What am I doing wrong?
Related
I have created a plugin architecture in C# app. In special folder I upload dlls and system search for certain interface and using reflection invokes function within plugin. But one of plugins (dlls) references to Open.XML dll which is not installed on the server where app is running. Is it a way to create a plugin ( compile it ?) that contains all libraries that it needs. Or it should be done in a different way?
1) Distribute any required DLLs together with the plugin DLL, and put them inside the plugin folder. Either add the plugin folder to the probing path for assemblies in the app.config, or add a handler for the AssemblyResolve event.
2) Use ILMerge to combine the plugin and required assemblies into one assembly.
If you load all plugins into the same app domain, this will cause funny issues if the same types are merged into multiple plugins.
I have an Outlook plugin created that uses MEF to load extensions. The extensions are all created as C# class libraries. When the Outlook plugin starts, it copies all the plugin DLLs from a network directory to the local computer and then loads them via MEF.
For one of them, I'm using the MySql.Data.dll library. That dll is copied to the same directory where I place the DLL's which MEF loads in, but that one isn't working. The end user gets an exception saying it can't find that MySql dll.
What's the trick to placing extra DLLs that are needed by a class library included via an MEF import?
I haven't used MEF in a project but I have had to roll my own plug-in architecture on a couple of occassions. Something you can try is hooking in to the AppDomain.AssemblyResolve event. I don't know how useful the example is on that page but you could examine the assembly name in the event args and attempt to load that assembly from the same folder you are loading the plug-ins from.
I wrote a dll c++/cli library which uses my other c# dll library. C++/cli library works fine when I've got c# dll in the same folder as application which calls it. This library will be finally loaded to many applications and a C# dll must not be copied into directory with application. It has to be in the same folder as c++/cli library, but in that cases I've got System.IO.FileNotFoundException.
My suggestion is to load c# library manually or to change path where f.ex. firefox is looking for dependencies, but I tried with LoadLibrary() and Assembly::LoadFrom() methods to force loading from right directory. Of course I added directory path with dll to system PATH.
I work on VS2010.
You don't change the default directory where an application will look for dlls.
At design time put your dll in some well know location, the one you are going to deploy to. Add a reference to it, make sure it's set to Don't copy ever, otherwise it will end up in the bin folder. You have to do this otherwise it won't compile.
When you deploy, you'll need one package to deploy common dlls, and one for each application. Careful you don't create your own version of dll hell, if appA needs an older or new version of the common dll, compared to AppB
Add an AppDomain.AssemblyResolve event to main (for windows app). At run time the event handler will get fired when you reference a type in your dll, and the assembly has not yet been loaded.
In there you load it from the well known location. That usually in config, or in a relative path.
E.g.
AllMyApps
CommonDLLS
MyFirstApp
So the path you load the required common dll from would be "..\CommonDlls\MyCommondll.dll".
NB you will want to secure the dlls in some way, otherwise a bad guy might be able to inject their version of one in to your app, which would be bad...
You can use this mechanism to get the dll from a remote server or a database blob as well.
The simplest case is only a few lines of code, just look the event up. Took me about 15 minutes to get this going in a similar scenario.
Not on this machine though, otherwise I'd have pasted in the code.
We are trying to program a couple of plugins for another application. We have two directories each with the code it needs to run independently whcih contain all the dll's (but not the exe as its 3rd party and we have no control over it). There is some shared code in a dll, placed in each plugin directory. When introducing a new version of the plugin we need to change this shared dll in one of the plugin directories but leave the other. When we do this the old version breaks as it relies on the older version of the shared dll but it only loads one. Is there a way to force it to use a certain version of the dll?
you should use the latebinding approach System.Reflection
I'm attempting to implement a C++ DLL (of my own creation) that uses the Intel Performance Primitives in a C# forms application. I'm getting a "DLL Not Found Exception" when I attempt to run the program. One possible reason put forward in other posts on this site is that there are dependent DLLs that must be referenced and in fact after downloading DpendencyWalker I found that my DLL uses "IPPS-7.0.DLL".
My problem is that it is unclear to me how to reference these dependent DLLs. I've added the IPPS-7.0.DLL containing folder to referenced paths as well as added references to the "IntelCppOptPkg" and "IntelLibOptPgk" assemblies but this has not solved the problem.
So, am I correct in believing this is the problem? And if so, how does one reference a depedent DLL in managed code?
Thank you.
You don't reference them, they are not .NET assemblies. You just need to make sure that the DLL(s) get copied to your build directory. Easiest way to do that is with Project + Add Existing Item, select the DLL from wherever it was copied. Then select the added file and in the Properties window set Build Action = Content, Copy to Output Directory = Copy if newer. Checking-in the DLL(s) in source control is generally a good idea btw.
Managed code can not reference unmanaged dll the same way it references managed assemblies. Managed references actually change the meta data of your assembly:
The compiler records static
references in the assembly manifest's metadata at build time.
...
The preferred way to reference an assembly is to use a full reference,
including the assembly name, version, culture, and public key token
(if one exists).
Native dlls simply don't have this .NET meta data associated with them. They have to be copied manually in the Post Build step or during deployment. There is a workaround but I don't think it will work if your managed app is platform independent (Any CPU) and you have x86 and x64 versions of unmanaged dlls.