Dynamic dll loading in C #

I have a window for editing. The editor must load the DLL (which I have full control) in response to the user's choice, in order to know how to visually display the information. (They are dll, because the user does not necessarily want or needs each separate display model, and also allows you to add new ones without interfering with the main project).

All of them will just be saved in a subdirectory (for now anyway) I'm sure I can list the available DLLs, but I need to do 2 more things that I'm not sure

1) Some way to get metadata from \ on the dll, so I can create lists of possible display options ...

2) Download the selected dll and unload it if necessary

Any suggestions are welcome.

0
c # dll
Nov 17 '09 at 18:40
source share
6 answers

Learn how to do this very simply using MEF, just use the DirectoryCatalog specified in your plugin, and as long as you have the corresponding [Export] and [Import] options, it works great.

0
Aug 29 2018-11-11T00:
source share

If you are using raw dll and not .NET assemblies, here are some handy P / Invokes for you:

[DllImport("kernel32.dll", CharSet=CharSet.Auto)] private static extern IntPtr LoadLibrary(string lpFileName); [DllImport("kernel32.dll", CharSet=CharSet.Auto)] private static extern void SetDllDirectory(string lpPathName); [DllImport("kernel32.dll", CharSet=CharSet.Auto)] privatestatic extern int GetModuleFileName(IntPtr module, [Out] StringBuilder fileName, int size); [DllImport("kernel32.dll", CharSet=CharSet.Auto)] private static bool FreeLibrary(IntPtr module); [DllImport("kernel32.dll", CharSet=CharSet.Auto)] private IntPtr GetProcAddress(IntPtr hModule, string lpProcName); 

Please note that SetDllDirectory may need some protection because it is not available for all versions of Windows (Windows 2000, in particular, does not have it).

And when using:

 SetDllDirectory(candidateFolder); IntPtr dllHandle = LoadLibrary(dllName); if (dllHandle != IntPtr.Zero) { _dllHandle = dllHandle; _location = candidateFolder; _fullPath = Path.Combine(candidateFolder, dllName); IntPtr p = GetProcAddress(_dllHandle, procName); if (p == IntPtr.Zero) throw new ArgumentException("procName"); SomeDelegateType d = (SomeDelegateType)Marshal.GetDelegateForFunctionPointer(p, typeof(SomeDelegateType)); d(/* args */); } 

Otherwise, you will use assembly methods. Considering assembly level attributes or object level attributes is a good way to get more information, although if you want it is a plug-in system, you should use a plug-in system, such as the CodePlex Managed Add-ons Framework . See also this question and answer .

+4
Nov 17 '09 at 18:45
source share

Take a look at the frames of Castle Windsor . It is designed to handle all of your requirements, including unloading a DLL. It is also free and open source.

+2
Nov 17 '09 at 19:02
source share

I don't know if there is a change in how your program works, but you can use dependency injection to do this if they stick to a specific interface.

The user chooses, you dynamically set the class to load, and then just get an instance of the class.

I do not deal with unloading, I’m just thinking about how you could get classes, and since the baseboard has already provided links to functions for working with dll, I think I’ll just end here.

+1
Nov 17 '09 at 18:47
source share

For your own module, the easiest way to get "metadata" is to define some C-export (not named) functions that return the information you need. In the simplest case, they return pointers to static data in modules, for example:

 extern "C" const char* GetModuleDescription(); ... const char* GetModuleDescription() { return "Dummy Module"; } 

Then you load each “.dll” file into the directory using LoadLibrary , load and call the known export from it using GetProcAddress . If you cannot upload a file or find an export, then it is not a valid plug-in module, so skip it.

Once you are done with the module, you can call FreeLibrary . Then, Windows will unload the module from your address space.

+1
Nov 17 '09 at 18:55
source share

OK, I realized that I need to use the second AppDomain, load the DLL into it, and then I can unload the AppDomain as needed.

 string SignalSystemDLLPath = AppDomain.CurrentDomain.BaseDirectory + MyApp.Properties.Resources.SystemModuleFolder; AppDomainSetup info = new AppDomainSetup(); info.ApplicationBase = DLLPath; DLLDomain = AppDomain.CreateDomain("EditorDomain", null, info); 

DLLPath is installed in a subdirectory that contains the dll.

Then I send to all the DLLs to get the AssemblyName, and then later I use

 DLLDomain.Load(SelectedAssemblyName) 

to load the dll. However, I keep getting FileNotFound exceptions. After long searches, I decided to work hard at the moment, and I can reorganize it later. If I really need to do this ...

Thank you for your responses!

0
Nov 19 '09 at 18:18
source share



All Articles