0

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.

Community
  • 1
  • 1
tearvisus
  • 2,013
  • 2
  • 15
  • 32
  • 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 Nov 17 '16 at 15:31
  • The behavior is the same even when there is nothing between the `sanbox.Load` and `AppDomain.Unload` instructions. – tearvisus Nov 18 '16 at 06:57

1 Answers1

1

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);
JuanR
  • 7,405
  • 1
  • 19
  • 30
  • Unfortunately, it does not work. The second check still prints true. – tearvisus Nov 16 '16 at 23:34
  • What if to call `IsAssemblyLoaded()` before `Check` call? May be It has been loaded earlier? – Jury Soldatenkov Nov 17 '16 at 11:33
  • By the 'second check' I meant the second `IsAssemblyLoaded` invocation. The `Check` method in this example is called exactly once. – tearvisus Nov 17 '16 at 13:08
  • I mean that something may load it occasionally. So my advice was to validate the assumption by calling `IsAsseblyLoaded` frist. – Jury Soldatenkov Nov 17 '16 at 13:57
  • I agree with @JurySoldatenkov. Try calling IsAssemblyLoaded before you even try to load it yourself to see if something else has already done it without you realizing it. – JuanR Nov 17 '16 at 14:02
  • I added another `IsAssemblyLoaded` call immediately before the `sandbox.Load` invocation. It returns false. – tearvisus Nov 18 '16 at 06:55
  • Thank you for trying @tearvisus. Is your assembly strongly typed? – JuanR Nov 18 '16 at 14:36
  • I mean to say strongly named, sorry. – JuanR Nov 18 '16 at 14:42
  • I've checked all four combinations: loaded assembly strongly named/not strongly named, executing application strongly named/not strongly named. The behavior is the same in all four cases. – tearvisus Nov 19 '16 at 10:17
  • Did you try using the MultiDomainHost enumeration value instead for the LoaderOptimization property of the AppDomainSetup class? (assuming your assembly is not strongly typed and it has not been registered in the GAC). – JuanR Nov 21 '16 at 21:10
  • Yes, I've tried with no success. I've checked all values of the `LoaderOptimation`, none of them works. – tearvisus Nov 22 '16 at 21:50