创建自定义AppDomain并向其添加程序集

时间:2013-06-20 23:04:16

标签: c# reflection assemblies appdomain

如何创建appdomain,向其添加程序集,然后销毁该app域?这就是我的尝试:

    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!            
    }

我也尝试过:

myDomain.Load(File.ReadAllBytes(pathToExe)); 

如何将程序集添加到appdomain。一旦我这样做,我可以通过反射找到方法执行它,然后销毁appdomain

我得到的例外是:

  

无法加载文件或程序集'ConsoleApplication1,Version = 1.0.0.0,   Culture = neutral,PublicKeyToken = null'或其依赖项之一。该   系统找不到指定的文件。

1 个答案:

答案 0 :(得分:11)

两个快点:

  1. AppDomain.Load在当前AppDomain中加载程序集而不在myDomain上加载(很奇怪,我知道)。
  2. AppDomain.LoadLoad上下文中加载程序集,该程序集从apps base-dir,private-bin-paths和GAC解析程序集。最有可能的是,您尝试加载的程序集不在任何这些解释异常消息的位置。
  3. 有关详细信息,请查看此answer

    将程序集加载到AppDomain的一种方法是创建MarshalByRef派生的加载程序。您需要这样的东西,以避免泄漏类型(和程序集)到您的主AppDomain。这是一个简单的:

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

    并使用它:

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