DLL loading into a separate AppDomain

I am writing a plugin architecture. My dll plugins are in the subdirectory from which the plugin manager is launched. I load plugins into a separate AppDomain as follows:

string subDir;//initialized to the path of the module directory. AppDomainSetup setup = new AppDomainSetup(); setup.PrivateBinPath = subDir; setup.ApplicationBase = subDir; AppDomain newDomain= AppDomain.CreateDomain(subDir, null, setup); byte[] file = File.ReadAllBytes(dllPath);//dll path is a dll inside subDir newDomain.Load(file); 

But. newDomain.Load returns the assembly that the current domain is trying to load. Since the DLL plugin is in a subdirectory, the current domain cannot and should not see these DLLs, and the current domain throws a FileLoadException "ex = {" Failed to load the file or assembly ... or one of its dependencies. "

The question is, can we load the assembly into a separate AppDomain without returning the loaded assembly?

I know that I can add a handler for the AssemblyResolve event in the current domain and return zero, but I would prefer not to go this route.

Thanks in advance.

+4
source share
2 answers

You can also use DoCallBack - here I collected something after reading lots about him on SO. This creates an appdomain, verifies that the assemblies have the same public signature key, loads the assembly, executes the static method, unloads the appdomain, and then removes the dll.

 static void Main(string[] args) { string unknownAppPath = @"path-to-your-dll"; Console.WriteLine("Testing"); try { AppDomainSetup setup = new AppDomainSetup(); setup.AppDomainInitializer = new AppDomainInitializer(TestAppDomain); setup.AppDomainInitializerArguments = new string[] { unknownAppPath }; AppDomain testDomain = AppDomain.CreateDomain("test", AppDomain.CurrentDomain.Evidence, setup); AppDomain.Unload(testDomain); File.Delete(unknownAppPath); } catch (Exception x) { Console.WriteLine(x.Message); } Console.ReadKey(); } public static void TestAppDomain(string[] args) { string unknownAppPath = args[0]; AppDomain.CurrentDomain.DoCallBack(delegate() { //check that the new assembly is signed with the same public key Assembly unknownAsm = AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(unknownAppPath)); //get the new assembly public key byte[] unknownKeyBytes = unknownAsm.GetName().GetPublicKey(); string unknownKeyStr = BitConverter.ToString(unknownKeyBytes); //get the current public key Assembly asm = Assembly.GetExecutingAssembly(); AssemblyName aname = asm.GetName(); byte[] pubKey = aname.GetPublicKey(); string hexKeyStr = BitConverter.ToString(pubKey); if (hexKeyStr == unknownKeyStr) { //keys match so execute a method Type classType = unknownAsm.GetType("namespace.classname"); classType.InvokeMember("method-you-want-to-invoke", BindingFlags.InvokeMethod, null, null, null); } }); } 
+4
source

As indicated in the links below:

Loading / unloading assemblies in different AppDomain

Download the assembly to the new AppDomain without loading it into the Parent AppDomain

It seems that calling the Load() method on another AppDomain object causes the assembly to load into the current AppDomain .

The solution is to use the CreateInstanceFromAndUnwrap() method of the AppDomain class instead. You pass the assembly path and type to convert.

+2
source

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


All Articles