Unloading the Assembly Loaded with Assembly.Loadfrom()

Unloading the Assembly loaded with Assembly.LoadFrom()

Unfortunately you can not unload an assembly once it is loaded. But you can unload an AppDomain. What you can do is to create a new AppDomain (AppDomain.CreateDomain(...) ), load the assembly into this appdomain to work with it, and then unload the AppDomain when needed. When unloading the AppDomain, all assemblies that have been loaded will be unloaded. (See reference)

To call the garbage collector, you can use

GC.Collect(); // collects all unused memory
GC.WaitForPendingFinalizers(); // wait until GC has finished its work
GC.Collect();

GC calls the finalizers in a background thread, that's why you have to wait and call Collect() again to make sure you deleted everything.

is it possible to unload an Assembly loaded dynamically in dotnet core?

Check out this link here

The unload api is not yet completed.

namespace System.Runtime.Loader
{
public class AssemblyLoadContext
{
// Allow to create an unloadable ALC. The default constructor
// will call this method with false
protected AssemblyLoadContext(bool unloadable);

// Returns true if this ALC is collectible
public bool Unloadable {get; }

// Allows to explicitly unload an ALC. Once this method is called,
// any call to LoadFromXXX method will throw an exception
public void Unload();
}
}

there's an open issue for the unload api and the api has been approved probably released in the future version as the milestone is under Future tag.

dynamically loading and unloading of c# assembly into appdomain

I found that Assembly.LoadFile(...) will lock the file, even beyond the point of unloading the AppDomain.

My solution is to first load the assembly bytes into memory, and then load it into the AppDomain:

var assemblyBytes = System.IO.File.ReadAllBytes("myassembly.dll");
var assembly = System.Reflection.Assembly.Load(assemblyBytes);

That way the file is never locked and you can delete it, etc.

There's a better answer to a similar question here.

Unload assemblies

You can use in-memory assembly:

Get-ChildItem -Path $input -Filter '*.dll' | ForEach-Object {
$assembly = [System.Reflection.Assembly]::Load([IO.File]::ReadAllBytes($_.FullName))
Write-Host $assembly.FullName
}

Loading/Unloading assembly in different AppDomain

Try this:

namespace SeperateAppDomainTest
{
class Program
{
static void Main(string[] args)
{
LoadAssembly();
}

public static void LoadAssembly()
{
string pathToDll = Assembly.GetExecutingAssembly().CodeBase;
AppDomainSetup domainSetup = new AppDomainSetup { PrivateBinPath = pathToDll };
var newDomain = AppDomain.CreateDomain("FooBar", null, domainSetup);
ProxyClass c = (ProxyClass)(newDomain.CreateInstanceFromAndUnwrap(pathToDll, typeof(ProxyClass).FullName));
Console.WriteLine(c == null);

Console.ReadKey(true);
}
}

public class ProxyClass : MarshalByRefObject { }

c# .NET Loading/Unloading assembly while keeping the same session

to load the assemblies in the same AppDomain but not lock the files after load just use the LoadFrom method in this way:

Assembly asm = Assembly.LoadFrom( “mydll.dll” );

in this way you are done and Session will be available.

there will be an issue with the debugger because symbols (*.pdb) will not get loaded so no breakpoint and no debugging available, to be able to debug you should really load the .pdb files in memory as well, for example using FileStream.

Edit: The way you can do to also load symbols and not lock the files is to use proper overload of Assembly.Load, the one that gets two byte[] one for the assembly and the other for the assembly' symbols file (.pdb file):

public static Assembly Load(
byte[] rawAssembly,
byte[] rawSymbolStore
)

in fact you should first load the bytes with a stream then call Assembly.Load and pass the byte[]

EDIT 2:

here a full example to load the assemblies in your current domain, including the symbol file and not having the files locks.

it's a full example found online, it reflect everything you need including the handling of AppDomain.AssemblyResolve...

public static void Main() {
AppDomain currentDomain = AppDomain.CurrentDomain;

currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolver);
}

static void InstantiateMyType(AppDomain domain) {
try {
// You must supply a valid fully qualified assembly name here.
domain.CreateInstance("Assembly text name, Version, Culture, PublicKeyToken", "MyType");
} catch (Exception e) {
Console.WriteLine(e.Message);
}
}

// Loads the content of a file to a byte array.
static byte[] loadFile(string filename) {
FileStream fs = new FileStream(filename, FileMode.Open);
byte[] buffer = new byte[(int) fs.Length];
fs.Read(buffer, 0, buffer.Length);
fs.Close();

return buffer;
}

static Assembly MyResolver(object sender, ResolveEventArgs args) {
AppDomain domain = (AppDomain) sender;

// Once the files are generated, this call is
// actually no longer necessary.
EmitAssembly(domain);

byte[] rawAssembly = loadFile("temp.dll");
byte[] rawSymbolStore = loadFile("temp.pdb");
Assembly assembly = domain.Load(rawAssembly, rawSymbolStore);

return assembly;
}


Related Topics



Leave a reply



Submit