Reputation: 2033
I'm trying to check some metadata of an assembly without loading it (permanently) into my app. To do this, I create a temporary sandbox
AppDomain, load the assembly into it and then unload the whole sandbox
. According to the answers to this question that's "correct" way to do it.
However after unloading the assembly it still remains in the current AppDomain. Why?
The answer to this question suggest that the assembly can be "bled into" the current domain, but I don't see how can this be possible in my example. The rest of the application does not use the assembly at all, it's not even referenced. The observed behavior persists even when I unload the sandobx
immediately after the assembly load.
This article says that domain-neutral assemblies cannot be unloaded this way. Is that the reason? If yes, can I somehow stop the assembly from being treated as domain-neutral?
private void Check()
{
string assemblyName = "SomeUnrelatedAssembly";
var sandbox = AppDomain.CreateDomain("sandbox"); //create a discardable AppDomain
//load the assembly to the sandbox
byte[] arr;
using (var memoryStream = new MemoryStream())
{
using (var fileStream = new FileStream($"{assemblyName}.dll", FileMode.Open))
fileStream.CopyTo(memoryStream);
arr = memoryStream.ToArray();
}
Console.WriteLine(IsAssemblyLoaded(assemblyName)); //prints false
sandbox.Load(arr);
//and unload it
AppDomain.Unload(sandbox);
Console.WriteLine(IsAssemblyLoaded(assemblyName)); //prints true!
}
private static bool IsAssemblyLoaded(string assemblyName)
{
return AppDomain.CurrentDomain.GetAssemblies().Any(a => a.FullName.Contains(assemblyName));
}
EDIT: I've checked the loading process with Process Explorer (like this). The loaded assembly is NOT domain-neutral.
Upvotes: 0
Views: 2011
Reputation: 7783
You are correct. Your assembly is being deemed domain-neutral and shared across app domains.
Use the AppDomain.CreateDomain overload that allows you to provide setup information:
Info:
AppDomainSetup info = new AppDomainSetup();
info.ApplicationBase = domainDir;
info.ApplicationName = executableNameNoExe;
info.LoaderOptimization = LoaderOptimization.SingleDomain;
Change:
AppDomain.CreateDomain("sandbox");
To:
AppDomain.CreateDomain("sandbox",null, info);
Upvotes: 1