0
votes

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.

1
can you show us what //check some metadata code looks like? It's possible that you go through metadata in the current domain although load assembly in a sandbox domain. - Jury Soldatenkov
The behavior is the same even when there is nothing between the sanbox.Load and AppDomain.Unload instructions. - tearvisus

1 Answers

1
votes

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);