将当前程序集加载到不同的 AppDomain 中 [英] Load Current Assembly into different AppDomain

查看:32
本文介绍了将当前程序集加载到不同的 AppDomain 中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个具有不同基目录的 AppDomain.但是,如果基目录中没有当前正在执行的程序集的副本,我似乎无法将当前正在执行的程序集加载到另一个 AppDomain 中.我什至试图从字节加载它.

I have created an AppDomain with a different base directory. However, I cannot seem to load the currently executing assembly into the other AppDomain without having a copy of the current executing assembly in the base directory. I've even tried to load it from the bytes.

当我尝试加载时没有例外,但是当我尝试使用时:

I get no exception when I try to load, but when I try to use:

domain.DoCallBack(new CrossAppDomainDelegate(... 

我明白了:

无法加载文件或程序集..........系统找不到指定的文件.

Could not load file or assembly ........... The system cannot find the file specified.

我的代码如下:

private static void SaveAssemblies(Assembly ass, List<byte[]> assemblyByteList)
{
    AssemblyName[] assNames = ass.GetReferencedAssemblies();
    foreach (AssemblyName assName in assNames)
    {
        Assembly referedAss = Assembly.Load(assName);
        if (!referedAss.GlobalAssemblyCache)
        {
            SaveAssemblies(referedAss, assemblyByteList);
        }
    }
    byte[] rawAssembly = File.ReadAllBytes(ass.Location);
    assemblyByteList.Add(rawAssembly);
}

public static AppDomain CreateAppDomain(string dir, string name)
{
    AppDomainSetup domainSetup = new AppDomainSetup();
    domainSetup.ApplicationBase = dir;
    domainSetup.ApplicationName = Path.GetFileName(dir);
    domainSetup.PrivateBinPath = Path.Combine(dir, "Libs");

    AppDomain domain = AppDomain.CreateDomain(name, null, domainSetup);
    //Load system assemblies needed for the module
    List<byte[]> assemblyByteList = new List<byte[]>();
    SaveAssemblies(Assembly.GetExecutingAssembly(), assemblyByteList);

    foreach (byte[] rawAssembly in assemblyByteList)
        domain.Load(rawAssembly);

    domain.DoCallBack(new CrossAppDomainDelegate(SetupLogging));
    return domain;
}

更新:

如果我查看输出,我看到这个程序集似乎已加载

It seems the assembly is loaded if i look in output i see this

TaskExecuter.Terminal.vshost.exe"(托管 (v4.0.30319)):加载NLog"TaskExecuter.Terminal.vshost.exe"(托管 (v4.0.30319)):已加载TaskExecuter",已加载符号.

'TaskExecuter.Terminal.vshost.exe' (Managed (v4.0.30319)): Loaded 'NLog' 'TaskExecuter.Terminal.vshost.exe' (Managed (v4.0.30319)): Loaded 'TaskExecuter', Symbols loaded.

但我仍然得到例外...我不明白这一点

but i still get the exception... i don't understand this

System.IO.FileNotFoundException 未处理 Message=无法加载文件或程序集任务执行器,版本=1.0.4244.31921,Culture=neutral, PublicKeyToken=null' 或其依赖项之一.这系统找不到指定的文件.源=mscorlib
文件名=任务执行器,版本=1.0.4244.31921,文化=中性,PublicKeyToken=null FusionLog==== 预绑定状态信息 ===LOG: User = Peter-PC\Peter LOG: DisplayName = TaskExecuter,版本=1.0.4244.31921,文化=中性,PublicKeyToken=null(完全指定)日志:Appbase =file:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks 日志:初始PrivatePath = C:\ProgramData\TaskExecuter\TaskLib\uTorrentTasks\Libs调用程序集:(未知).=== LOG:此绑定在默认加载上下文中启动.日志:使用应用配置文件:d:\users\peter\documents\visual studio2010\Projects\TaskExecuter\TaskExecuter.Terminal\bin\Release\TaskExecuter.Terminal.vshost.exe.ConfigLOG:使用主机配置文件:LOG:使用机器配置文件来自C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.日志:此时未将策略应用于参考(私人,自定义、部分或基于位置的程序集绑定).日志:尝试下载新网址file:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/TaskExecuter.DLL.日志:尝试下载新 URLfile:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/TaskExecuter/TaskExecuter.DLL.日志:尝试下载新 URLfile:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/Libs/TaskExecuter.DLL.日志:尝试下载新 URLfile:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/Libs/TaskExecuter/TaskExecuter.DLL.日志:尝试下载新 URLfile:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/TaskExecuter.EXE.日志:尝试下载新 URLfile:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/TaskExecuter/TaskExecuter.EXE.日志:尝试下载新 URLfile:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/Libs/TaskExecuter.EXE.日志:尝试下载新 URLfile:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/Libs/TaskExecuter/TaskExecuter.EXE.

System.IO.FileNotFoundException was unhandled Message=Could not load file or assembly 'TaskExecuter, Version=1.0.4244.31921, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified. Source=mscorlib
FileName=TaskExecuter, Version=1.0.4244.31921, Culture=neutral, PublicKeyToken=null FusionLog==== Pre-bind state information === LOG: User = Peter-PC\Peter LOG: DisplayName = TaskExecuter, Version=1.0.4244.31921, Culture=neutral, PublicKeyToken=null (Fully-specified) LOG: Appbase = file:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks LOG: Initial PrivatePath = C:\ProgramData\TaskExecuter\TaskLib\uTorrentTasks\Libs Calling assembly : (Unknown). === LOG: This bind starts in default load context. LOG: Using application configuration file: d:\users\peter\documents\visual studio 2010\Projects\TaskExecuter\TaskExecuter.Terminal\bin\Release\TaskExecuter.Terminal.vshost.exe.Config LOG: Using host configuration file: LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). LOG: Attempting download of new URL file:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/TaskExecuter.DLL. LOG: Attempting download of new URL file:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/TaskExecuter/TaskExecuter.DLL. LOG: Attempting download of new URL file:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/Libs/TaskExecuter.DLL. LOG: Attempting download of new URL file:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/Libs/TaskExecuter/TaskExecuter.DLL. LOG: Attempting download of new URL file:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/TaskExecuter.EXE. LOG: Attempting download of new URL file:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/TaskExecuter/TaskExecuter.EXE. LOG: Attempting download of new URL file:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/Libs/TaskExecuter.EXE. LOG: Attempting download of new URL file:///C:/ProgramData/TaskExecuter/TaskLib/uTorrentTasks/Libs/TaskExecuter/TaskExecuter.EXE.

堆栈跟踪:在 System.Reflection.RuntimeAssembly._nLoad(AssemblyName文件名、字符串代码库、证据程序集安全性、运行时程序集locationHint、StackCrawlMark&stackMark,布尔 throwOnFileNotFound,布尔用于内省,布尔抑制安全检查)在 System.Reflection.RuntimeAssembly.nLoad(AssemblyName文件名、字符串代码库、证据程序集安全性、运行时程序集locationHint、StackCrawlMark&stackMark,布尔 throwOnFileNotFound,布尔用于内省,布尔抑制安全检查)在System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyNameassemblyRef、证据程序集安全性、StackCrawlMark&堆栈标记,布尔用于内省,布尔抑制安全检查)在 System.Reflection.RuntimeAssembly.InternalLoad(StringassemblyString、证据程序集安全性、StackCrawlMark&堆栈标记,内省的布尔值)在 System.Reflection.Assembly.Load(String assemblyString)在System.Runtime.Serialization.FormatterServices.LoadAssemblyFromString(String程序集名称)在System.Reflection.MemberInfoSerializationHolder..ctor(SerializationInfo信息,StreamingContext 上下文)在 System.AppDomain.DoCallBack(CrossAppDomainDelegate回调委托)在 TaskExecuter.AppDomainHelper.CreateAppDomain(String dir,字符串名称)在 d:\users\peter\documents\visual studio2010\Projects\TaskExecuter\TaskExecuter\AppDomainHelper.cs:line 50在 TaskExecuter.TaskManagment.TaskFinder.Probe() 中d:\users\peter\documents\visual studio2010\Projects\TaskExecuter\TaskExecuter\TaskManagment\TaskFinder.cs:line29在 TaskExecuter.TaskManagment.TaskManager.LoadTasks() 中d:\users\peter\documents\visual studio2010\Projects\TaskExecuter\TaskExecuter\TaskManagment\TaskManager.cs:line63在 TaskExecuter.TaskManagment.TaskManager.Start() 中d:\users\peter\documents\visual studio2010\Projects\TaskExecuter\TaskExecuter\TaskManagment\TaskManager.cs:line95在 TaskExecuter.Terminal.Program.Main(String[] args) 中d:\users\peter\documents\visual studio2010\Projects\TaskExecuter\TaskExecuter.Terminal\Program.cs:line 16在 System.AppDomain._nExecuteAssembly(RuntimeAssembly 程序集,字符串 [] 参数)在 System.AppDomain.ExecuteAssembly(String assemblyFile,证据 assemblySecurity,String[] args)在Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()在 System.Threading.ThreadHelper.ThreadStart_Context(Object状态)在 System.Threading.ExecutionContext.Run(ExecutionContextexecutionContext, ContextCallback 回调, 对象状态, 布尔值忽略SyncCtx)在 System.Threading.ExecutionContext.Run(ExecutionContextexecutionContext, ContextCallback 回调, 对象状态)在 System.Threading.ThreadHelper.ThreadStart()
内部异常:

StackTrace: at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection, Boolean suppressSecurityChecks) at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) at System.Reflection.Assembly.Load(String assemblyString) at System.Runtime.Serialization.FormatterServices.LoadAssemblyFromString(String assemblyName) at System.Reflection.MemberInfoSerializationHolder..ctor(SerializationInfo info, StreamingContext context) at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate) at TaskExecuter.AppDomainHelper.CreateAppDomain(String dir, String name) in d:\users\peter\documents\visual studio 2010\Projects\TaskExecuter\TaskExecuter\AppDomainHelper.cs:line 50 at TaskExecuter.TaskManagment.TaskFinder.Probe() in d:\users\peter\documents\visual studio 2010\Projects\TaskExecuter\TaskExecuter\TaskManagment\TaskFinder.cs:line 29 at TaskExecuter.TaskManagment.TaskManager.LoadTasks() in d:\users\peter\documents\visual studio 2010\Projects\TaskExecuter\TaskExecuter\TaskManagment\TaskManager.cs:line 63 at TaskExecuter.TaskManagment.TaskManager.Start() in d:\users\peter\documents\visual studio 2010\Projects\TaskExecuter\TaskExecuter\TaskManagment\TaskManager.cs:line 95 at TaskExecuter.Terminal.Program.Main(String[] args) in d:\users\peter\documents\visual studio 2010\Projects\TaskExecuter\TaskExecuter.Terminal\Program.cs:line 16 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()
InnerException:

推荐答案

我能够使用 archive.org 恢复指向博客文章的链接,并提出了一个可行的解决方案.

I was able to recover the linked to blog post using archive.org and also come up with a working solution.

我的目标是将 exe 动态编译到一个临时位置,然后让该 exe 影子加载子应用程序域中的所有主 dll,以便可以轻松更新生成 exe 的主应用程序.基本方法是使用 childAppDomain.CreateInstanceFrom 创建一个类型,该类型在构造函数中安装程序集解析事件处理程序.我的代码看起来像

My goal was to dynamically compile an exe into a temporary location, and then have that exe shadow load all main dlls in a child appdomain so that the main application that spawned the exe can be updated easily. The basic approach is using childAppDomain.CreateInstanceFrom to create a type that in the constructor installs the assembly resolve event handler. My code looked like

var exportAppDomain = AppDomain.CreateDomain(
    runnerName,
    null,
    appDomainSetup,
    new PermissionSet(PermissionState.Unrestricted));

exportAppDomain.CreateInstanceFrom(
    Assembly.GetExecutingAssembly().Location,
    "ExportLauncher.AppDomainResolver",
    true,
    BindingFlags.Public | BindingFlags.Instance,
    null,
    new object[] { Assembly.GetExecutingAssembly().Location },
    null,
    null);

以及创建所需的 AssemblyResolve 处理程序的类型(下面的博客文章描述了为什么需要另一种类型)

And the type that creates the needed AssemblyResolve handler (the blog post below describes why you need another type)

class AppDomainResolver
{
    string _sourceExeLocation;

    public AppDomainResolver(string sourceExeLocation)
    {
        _sourceExeLocation = sourceExeLocation;
        AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
    }

    Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        if (args.Name.Contains("exporterLauncher")) // why does it not already know it has this assembly loaded? the seems to be required
            return typeof(AppDomainResolver).Assembly;
        else
            return null;
    }
}

这是原始博客文章:

应用领域很难......

Application Domains is hard…

您是否曾经在 .NET 中使用过应用程序域?一开始看起来并没有那么困难,但是当您了解它们之后,您就会开始意识到所有的小困难.

Have you ever been working with Application Domain in .NET?, in the beginning it doesn’t seem all that difficult, but ones you get to know them you begin to realize all the little difficulties.

只要您不移动到 Host AppDomains.BaseDirectory 之外,一切都可以正常工作,但在我们的示例中,我们希望将插件部署在C:\My Plug-ins"位置,而宿主应用程序将运行在C:\Program Files\My App",因为我们可能会遇到从 AppDomain 到某些 Host Assemblies 的依赖问题,这显然是不可避免的.

Everything works fine as long as you don’t move outside the Host AppDomains.BaseDirectory, but in our case we wanted to have Plug-ins deployed at say location "C:\My Plug-ins" while the host application would run at "C:\Program Files\My App", since we might run into dependencies from the AppDomain to some of the Host Assemblies problems was apparently inevitable.

经典这是一些简单的代码和我们的第一次尝试.

The Classic Here is some simple code and our first attempt.

 1:  string applicationBase = Path.GetDirectoryName(interOperabilityPackageType.AssemblyDescription.AssemblyPath);
   2:  AppDomainSetup setup = new AppDomainSetup
   3:  {
   4:      ApplicationName = name,
   5:      ApplicationBase = applicationBase,
   6:      PrivateBinPath = AppDomain.CurrentDomain.BaseDirectory,
   7:      PrivateBinPathProbe = AppDomain.CurrentDomain.BaseDirectory,
   8:      ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
   9:  };
  10:   
  11:  Evidence evidence = new Evidence(AppDomain.CurrentDomain.Evidence);
  12:  AppDomain domain = AppDomain.CreateDomain(name, evidence, setup);

看起来很简单,但因为ApplicationBase"与AppDomain.CurrentDomain.BaseDirectory"不同,我们遇到了一个众所周知的异常.

Seems very simple, but because "ApplicationBase" is different from "AppDomain.CurrentDomain.BaseDirectory" we ran into what seems to be a very well know exception.

System.IO.FileNotFoundException: 无法加载文件或程序集Host.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"或其依赖项之一.系统找不到指定的文件.

System.IO.FileNotFoundException: Could not load file or assembly 'Host.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

如果您使用过任何类型的动态加载程序集,我敢肯定您对此很熟悉.问题是Host.Services"在主机应用程序域中是已知的,因为它存储在C:\Program Files\My App"中,而寻找它的应用程序域正在C:\My Plug-插入".

If you have worked with any sort of dynamically loading assemblies I am fairly sure that is familiar to you. And the issue is that "Host.Services" was know within the Host Application Domain because it is stored in "C:\Program Files\My App", and the Application Domain looking for it is looking in "C:\My Plug-ins".

好吧,我们以为我们指示它也查看AppDomain.CurrentDomain.BaseDirectory",即C:\Program Files\My App",但事实并非如此.

Well we Thought we instructed it to also look in "AppDomain.CurrentDomain.BaseDirectory" which would be "C:\Program Files\My App", but that was not the case.

AppDomain.AssemblyResolve 来救援?好的,所以我们之前一直在处理这些怪癖,所以我们知道如何使用AppDomain.AssemblyResolve"来手动解析 AppDomain 自身无法处理的任何程序集.

AppDomain.AssemblyResolve to the rescue? Ok so we have been working with these quirks before, so we knew how we could use "AppDomain.AssemblyResolve" to manually resolve any assemblies that the AppDomain it self could not handle.

1:  string applicationBase = Path.GetDirectoryName(interOperabilityPackageType.AssemblyDescription.AssemblyPath);
   2:  AppDomainSetup setup = new AppDomainSetup
   3:  {
   4:      ApplicationName = name,
   5:      ApplicationBase = applicationBase,
   6:      PrivateBinPath = AppDomain.CurrentDomain.BaseDirectory,
   7:      PrivateBinPathProbe = AppDomain.CurrentDomain.BaseDirectory,
   8:      ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
   9:  };
  10:   
  11:  Evidence evidence = new Evidence(AppDomain.CurrentDomain.Evidence);
  12:  AppDomain domain = AppDomain.CreateDomain(name, evidence, setup);
  13:  domain.AssemblyResolve += Resolve;

那应该是正确的,我们这么认为,又一次我们错了,现在发生的事情是,实际上并没有初始化应用程序域并使用它,而是在我们连接事件处理程序的地方失败了用于解析程序集.

That should work right, well we thought so and ones again we were wrong, what happens now is that instead of actually getting as far as initializing the Application Domain and using it, instead it fails right where we hooked up the event handler for resolving assemblies.

同样,异常看起来与前面提到的非常相似,但这次它找不到包含我们在上面代码片段的最后一行中设置的解析"处理程序的类型的程序集.

Again the exception looks very much like the previous mentioned, but this time it can’t find the Assembly that contains the Type that has the "Resolve" handler we set up in the very last line in the above snippet.

AppDomain.Load 然后!好的,很明显,当连接事件处理程序时,应用程序域需要知道处理该事件的对象的类型,当你考虑它时,这实际上是相当可以理解的,所以如果应用程序域甚至找不到那个并且负载我们真的无法处理任何事情.

AppDomain.Load then! Ok, so obviously when hooking up the event handler, the Application Domain needs to know the Type of the object handling that event, that is actually fairly understandable when you think about it, so if the Application Domain can’t even find that one and load we can’t really handle anything.

接下来是什么?我们的想法是手动指示应用程序域加载一个浅层程序集,该程序集没有可以在 GAC 中找到的任何其他依赖项,并挂钩一个事件处理程序.

So what is next? Our idea was to manually instruct the Application Domain to load a shallow assembly that didn’t have any other dependencies that what could be found in the GAC, and the hook an event handler up.

 1:  string applicationBase = Path.GetDirectoryName(interOperabilityPackageType.AssemblyDescription.AssemblyPath);
   2:  AppDomainSetup setup = new AppDomainSetup
   3:  {
   4:      ApplicationName = name,
   5:      ApplicationBase = applicationBase,
   6:      PrivateBinPath = AppDomain.CurrentDomain.BaseDirectory,
   7:      PrivateBinPathProbe = AppDomain.CurrentDomain.BaseDirectory,
   8:      ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
   9:  };
  10:   
  11:  Evidence evidence = new Evidence(AppDomain.CurrentDomain.Evidence);
  12:  AppDomain domain = AppDomain.CreateDomain(name, evidence, setup);
  13:  domain.Load(File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Host.AssemblyLoader.dll")));
  14:  domain.AssemblyResolve += new AssemblyLoader(AppDomain.CurrentDomain.BaseDirectory).Handle;

使用一个非常简单的小类,如下所示,不要介意奇怪的 Resolve 行为.

Using a very simple little class like the following, and don’t mind the odd Resolve behavior.

 1:  [Serializable]
   2:  public class AssemblyLoader
   3:  {
   4:      private string ApplicationBase { get; set; }
   5:   
   6:      public AssemblyLoader(string applicationBase)
   7:      {
   8:          ApplicationBase = applicationBase;
   9:      }
  10:   
  11:      public Assembly Resolve(object sender, ResolveEventArgs args)
  12:      {
  13:          AssemblyName assemblyName = new AssemblyName(args.Name);
  14:          string fileName = string.Format("{0}.dll", assemblyName.Name);
  15:          return Assembly.LoadFile(Path.Combine(ApplicationBase, fileName));
  16:      }
  17:  }

所以是或否?…不!…还是同样的问题.

So yes or no?… NO!… same problem still.

事情要简单得多!实际上,当我们设法让它发挥作用时,事情最终变得简单了许多.

Things are much more simple! Actually things became much more simple in the end when we managed to make it work.

我不能说 .NET 团队究竟如何设想这应该起作用,我们无法真正找出PrivateBinPath"和PrivateBinPathProbe"用于的任何有用的东西.好吧,我们现在使用它们,并使它们按预期工作!

I Can’t say how exactly the .NET team has envisioned that this should work, we couldn't really find out any useable things that the "PrivateBinPath" and "PrivateBinPathProbe" was used for. Well we use them now, and made them work as we expected they would!

因此我们将AssemblyLoader"类改为如下所示:

So we changed the "AssemblyLoader" class to look like this instead:

   1:  [Serializable]
   2:  public class AssemblyLoader : MarshalByRefObject
   3:  {
   4:      private string ApplicationBase { get; set; }
   5:   
   6:      public AssemblyLoader()
   7:      {
   8:          ApplicationBase = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath;
   9:          AppDomain.CurrentDomain.AssemblyResolve += Resolve;
  10:      }
  11:   
  12:      private Assembly Resolve(object sender, ResolveEventArgs args)
  13:      {
  14:          AssemblyName assemblyName = new AssemblyName(args.Name);
  15:          string fileName = string.Format("{0}.dll", assemblyName.Name);
  16:          return Assembly.LoadFile(Path.Combine(ApplicationBase, fileName));
  17:      }
  18:  }

因此,与其在我们创建应用程序域的地方连接事件,我们让类自己完成,并改为CurrentDomain".

So rather than hooking up the event where we created the Application Domain, we let the class do it by it self, and to "CurrentDomain" instead.

好的,等等,在工厂中创建它时会不会导致问题,因为它现在正在为错误的域加载?谢天谢地,您可以从外部在域内创建对象.

Ok so wait, doesn’t that cause an issue when creating it in the factory since it is now loading for the wrong domain? Well thankfully you are able to create objects within domains from the outside.

所以现在创建域如下:

1:  string applicationBase = Path.GetDirectoryName(interOperabilityPackageType.AssemblyDescription.AssemblyPath);
   2:  AppDomainSetup setup = new AppDomainSetup
   3:  {
   4:      ApplicationName = name,
   5:      ApplicationBase = applicationBase,
   6:      PrivateBinPath = AppDomain.CurrentDomain.BaseDirectory,
   7:      PrivateBinPathProbe = AppDomain.CurrentDomain.BaseDirectory,
   8:      ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
   9:  };
  10:   
  11:  Evidence evidence = new Evidence(AppDomain.CurrentDomain.Evidence);
  12:  AppDomain domain = AppDomain.CreateDomain(name, evidence, setup);
  13:  domain.CreateInstanceFrom(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Host.AssemblyLoader.dll"),"Host.AssemblyLoader");

我们甚至不关心维护对AssemblyLoader"的引用,因为它几乎应该通过将其自身连接到事件来保持活动状态.

We don’t even care for maintaining a reference to the "AssemblyLoader" since it should pretty much be kept alive by hooking it self up to the Event.

希望这可以帮助那些偶然发现相同问题的人,我看到许多解决方法,人们要么让插件安装在同一主机目录中,即使将所有必要的依赖项与插件一起部署它不是插件知道它依赖的东西等等.

Hopefully this can help some that has stumbled over the same problem, I see many workarounds where people then either just let Plug-ins be installed in same host directory, having all the necessary dependencies deployed along with the plug-in even though it isn’t something the plug-in knows it is dependant on and so forth.

以上至少使我们能够在远离主机应用程序基础的地方安装插件,我认为这很好.

The above at least enables us to install plug-ins away from our host application base which I think is nice.

如果有人以不同的方式解决了这个问题,那么请回复,也许我们可以找到两种方式的优缺点,或者只是找到更好的解决方案.

If anyone have solved this differently, then please make a response, maybe we can find pros and cons in either way, or just discover a better solution.

如果您有任何问题或无法使用上述方法,请随时提问.

If you have any questions or can’t get the above to work, then feel free to ask.

作者:Jens Melgaard |2010 年 7 月 1 日星期四下午 3:08 发布 |反馈 (0)

author: Jens Melgaard | posted @ Thursday, July 01, 2010 3:08 PM | Feedback (0)

这篇关于将当前程序集加载到不同的 AppDomain 中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆