[ACCEPTED]-How to unload an assembly from the primary AppDomain?-appdomain

Accepted answer
Score: 44

For .net versions core 3.0 and later:

You can now unload assemblies. Note that 15 appdomains are no longer available in .net 14 core. Instead, you can create one or more 13 AssemblyLoadContext, load your assemblies 12 via that context, then unload that context. See 11 AssemblyLoadContext, or this tutorial that simulates loading a plugin then unloading it.

For .net versions before .net core 3, including netframework 4 and lower

You can not unload an assembly from 10 an appdomain. You can destroy appdomains, but 9 once an assembly is loaded into an appdomain, it's 8 there for the life of the appdomain.

See 7 Jason Zander's explanation of Why isn't there an Assembly.Unload method?

If you are 6 using 3.5, you can use the AddIn Framework 5 to make it easier to manage/call into different 4 AppDomains (which you can unload, unloading 3 all the assemblies). If you are using versions 2 before that, you need to create a new appdomain 1 yourself to unload it.

Score: 29

I also know this is very old, but may help 13 someone who is having this issue! Here is 12 one way I have found to do it! instead of 11 using:

var assembly = Assembly.LoadFrom( FilePathHere );

use this:

var assembly = Assembly.Load( File.ReadAllBytes(FilePathHere));

This actually loads the "Contents" of 10 the assembly file, instead of the file itself. Which 9 means there is NOT a file lock placed on 8 the assembly file! So now it can be copied 7 over, deleted or upgraded without closing 6 your application or trying to use a separate 5 AppDomain or Marshaling!

PROS: Very Simple to 4 fix with a 1 Liner of code! CONS: Cannot use 3 AppDomain, Assembly.Location or Assembly.CodeBase.

Now 2 you just need to destroy any instances created 1 on the assembly. For example:

assembly = null;
Score: 16

You can't unload an assembly without unloading 23 the whole AppDomain. Here's why:

  1. You are running that 22 code in the app domain. That means there 21 are potentially call sites and call stacks 20 with addresses in them that are expecting 19 to keep working.

  2. Say you did manage to track 18 all handles and references to already running 17 code by an assembly. Assuming you didn't 16 ngen the code, once you successfully freed 15 up the assembly, you have only freed up 14 the metadata and IL. The JIT'd code is 13 still allocated in the app domain loader 12 heap (JIT'd methods are allocated sequentially 11 in a buffer in the order in which they are 10 called).

  3. The final issue relates to code 9 which has been loaded shared, otherwise 8 more formally know as "domain neutral" (check 7 out /shared on the ngen tool). In this 6 mode, the code for an assembly is generated 5 to be executed from any app domain (nothing 4 hard wired).

It is recommended that you design 3 your application around the application 2 domain boundary naturally, where unload 1 is fully supported.

Score: 11

You should load your temporary assemblies 2 in another AppDomain and when not in use then you 1 can unload that AppDomain. It's safe and fast.

Score: 5

If you want to have temporary code which 3 can be unloaded afterwards, depending on 2 your needs the DynamicMethod class might do what you 1 want. That doesn't give you classes, though.

Score: 1

Here is a GOOD example how to compile and 2 run dll during run time and then unload 1 all resources: http://www.west-wind.com/presentations/dynamicCode/DynamicCode.htm

Score: 1

I know its old but might help someone. You 3 can load the file from stream and release 2 it. It worked for me. I found the solution 1 HERE.

Hope it helps.

Score: 0

As an alternative, if the assembly was just 12 loaded in the first place, to check information 11 of the assembly like the publicKey, the 10 better way would be to not load it,and rather 9 check the information by loading just the 8 AssemblyName at first:

AssemblyName an = AssemblyName.GetAssemblyName ("myfile.exe");
byte[] publicKey = an.GetPublicKey();
CultureInfo culture = an.CultureInfo;
Version version = an.Version;

EDIT

If you need to reflect 7 the types in the assembly without getting 6 the assembly in to your app domain, you 5 can use the Assembly.ReflectionOnlyLoadFrom method. this will allow you 4 to look at they types in the assembly but 3 not allow you to instantiate them, and will 2 also not load the assembly in to the AppDomain.

Look 1 at this example as exlanation

public void AssemblyLoadTest(string assemblyToLoad)
{
    var initialAppDomainAssemblyCount = AppDomain.CurrentDomain.GetAssemblies().Count(); //4

    Assembly.ReflectionOnlyLoad(assemblyToLoad);
    var reflectionOnlyAppDomainAssemblyCount = AppDomain.CurrentDomain.GetAssemblies().Count(); //4

    //Shows that assembly is NOT loaded in to AppDomain with Assembly.ReflectionOnlyLoad
    Assert.AreEqual(initialAppDomainAssemblyCount, reflectionOnlyAppDomainAssemblyCount); // 4 == 4

    Assembly.Load(assemblyToLoad);
    var loadAppDomainAssemblyCount = AppDomain.CurrentDomain.GetAssemblies().Count(); //5

    //Shows that assembly is loaded in to AppDomain with Assembly.Load
    Assert.AreNotEqual(initialAppDomainAssemblyCount, loadAppDomainAssemblyCount); // 4 != 5
}

More Related questions