Replace DLL during use

I create a system with plugins with each plugin presented as a DLL. I would like to be able to restart them without stopping the main application. This means that they must be loaded at runtime, without pre-built links between them (search for files for dll and load them). I set this with Assembly.LoadFile(filename) , however, when I try to use File.Copy to replace the DLL, it throws an exception saying something similar to "used file". I tried using AppDomain by loading all plugins through this secondary domain and unloading it before rebooting, but this throws the same exception.

My current code is:

  if (pluginAppDomain != null) AppDomain.Unload(pluginAppDomain); foreach (string s in Directory.GetFiles(path_to_new_DLLs)) { string name = s.Substring(s.LastIndexOf('\\') + 1); Console.WriteLine("Copying " + name); File.Copy(s, Path.Combine(current_directory, name), true); // Throws exception here } AppDomainSetup setup = new AppDomainSetup(); setup.ApplicationBase = Environment.CurrentDirectory; setup.ShadowCopyFiles = "true"; // I think this is where the problem is, maybe I'm forgetting to set something pluginAppDomain = AppDomain.CreateDomain("KhybotPlugin", null, setup); foreach (String s in Directory.GetFiles(Environment.CurrentDirectory, "*.dll")) { int pos = s.LastIndexOf('\\') + 1; Assembly dll = pluginAppDomain.Load(s.Substring(pos, s.Length - pos - 4)); // Elided... Load types from DLL, etc, etc } 
+6
source share
3 answers

As a rule, you need to unload AppDomain for communication. If you want to prevent this error, you can simply load your DLL using Assembly.Load(Byte[]) .

You can also use the Managed Extensibility Framework , which will save you a lot of work.

Assembly.Load Release Solution

The assembly loaded using Assembly.LoadFrom () on the remote computer raises a SecurityException

+6
source

Loading DLL plugins into another AppDomain is the only solution - so you're on the right track. Beware of leakage of the object from the second application domain to the main one. You need all communication with the plugins to happen in the AppDomain plugin.

those. returning the plugin object to the main code is likely to lead to a plugin leak. Using builds for the main AppDomain.

Start with very simple code completely in the AppDomain plugin, for example, "load the assembly and create the class, but don’t return anything to the main domain." What is expanding use when you get more information about the relationship between AppDomains.

Note: if you are not doing this for educational purposes using an existing system (i.e. MEF ), better.

+2
source

You can do something like this ...

 if (pluginAppDomain != null) { AppDomain.Unload(pluginAppDomain); } //for each plugin pluginAppDomain = AppDomain.CreateDomain("Plugins Domain"); x = pluginAppDomain.CreateInstanceFromAndUnwrap("Plugin1.dll", "Namespace.Type"); 

You should not directly link to plugins in your main application. Put them in a separate project / s and access them through the interface.

0
source

Source: https://habr.com/ru/post/912243/


All Articles