How can I create an appdomain, add assemblies to it, then destroy that app domain? This is what I have tried:
static void Main(string[] args)
{
string pathToExe = @"A:\Users\Tono\Desktop\ConsoleApplication1.exe";
AppDomain myDomain = AppDomain.CreateDomain("MyDomain");
Assembly a = Assembly.Load(System.IO.File.ReadAllBytes(pathToExe));
myDomain.Load(a.FullName); // Crashes here!
}
I have also tried:
myDomain.Load(File.ReadAllBytes(pathToExe));
how can I add an assembly to the appdomain. Once I do that I can find the method via reflection execute it and then destroy the appdomain
The exception that I get is:
Could not load file or assembly 'ConsoleApplication1, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null' or one of its dependencies. The
system cannot find the file specified.
Two quick points:
AppDomain.Load
loads an assembly in the current AppDomain and not on myDomain
(weird, I know).
AppDomain.Load
loads an assembly in the Load
context, which resolves assemblies from the apps base-dir, the private-bin-paths and the GAC. Most probably, the assembly you try to load is not located in any of these locations which explains the exception message.
For more info have a look at this answer.
One way to load assemblies to an AppDomain is by creating a MarshalByRef-derived loader. You need something like this to avoid leaking types (and assemblies) to your main AppDomain. Here's a simple one:
public class SimpleAssemblyLoader : MarshalByRefObject
{
public void Load(string path)
{
ValidatePath(path);
Assembly.Load(path);
}
public void LoadFrom(string path)
{
ValidatePath(path);
Assembly.LoadFrom(path);
}
private void ValidatePath(string path)
{
if (path == null) throw new ArgumentNullException("path");
if (!System.IO.File.Exists(path))
throw new ArgumentException(String.Format("path \"{0}\" does not exist", path));
}
}
And use it like that:
//Create the loader (a proxy).
var assemblyLoader = (SimpleAssemblyLoader)myDomain.CreateInstanceAndUnwrap(typeof(SimpleAssemblyLoader).Assembly.FullName, typeof(SimpleAssemblyLoader).FullName);
//Load an assembly in the LoadFrom context. Note that the Load context will
//not work unless you correctly set the AppDomain base-dir and private-bin-paths.
assemblyLoader.LoadFrom(pathToExe);
//Do whatever you want to do.
//Finally unload the AppDomain.
AppDomain.Unload(myDomain);