2013-03-14 28 views
0

我正在为自动化调度程序编写一个插件体系结构,它需要健壮,所以我试图做ASP.NET/IIS风格的AppDomains - 即每个AppDomain是真的被视为它们自己独特的应用程序,它们之间没有共享对象。完整的ASP.NET风格的AppDomain程序集隔离

我在AppDomainSetup中设置ApplicationBase,ConfigurationFileShadowCopyFiles

自动化调度程序中有一个常见的程序集,我为每个插件加载 - 它处理加载插件的主程序集,捕获未捕获的异常和记录。有迹象表明,我已经确定这种方法也有一些不足:

  • 通过设置ApplicationBase到插件存储在何处,共同的组件(驻留在不同的路径)的任何依赖关系将不再得到解决。我通过挂钩AssemblyResolve事件破坏了这个工作,但这导致了其他问题。

  • 普通程序集和插件都有可能引用他们自己的同名命令程序集的副本 - 可能每个程序集都有不同的版本。或者也许是一个名称相同但内容完全不同的程序集。覆盖AssemblyResolve,插件的副本将始终首先加载。

  • 不是真的担心这个问题,但从安全角度来看,我认识到插件可能会重写调度器的依赖关系,导致它执行某些恶意的事情,或者反映到常见的程序集中并获取内部消息。

所以我决定,也许正确地做到这一点的唯一方法是根本就没有做到这一点 - 强制清洁的分离,任何组件不能加载到AppDomain中。我不确定要做什么最好的方法是什么,或者即使这是最好的方法。

您认为如何?

回答

0

我不确定这是否完全回答你的问题,但我们有一个类似的应用程序设置,我们有独立的子AppDomain和一个共享DLL文件夹,并且我们成功地使用了AssemblyResolve。

我们的文件结构为:

[PathToApplication]\OurApplication.exe 
[PathToApplication]\AddIns\[SharedAssemblies]\*.dll 
[PathToApplication]\AddIns\[FirstAddIn]\*.dll 
[PathToApplication]\AddIns\[SecondAddIn]\*.dll 

凡在方括号中的部分由实际路径替换。

在我们的例子中,共享程序集也是由主AppDomain加载的,所以我们在主要的App.config中设置如下。

<runtime> 
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
    <probing privatePath="AddIns\[SharedAssemblies]" /> 
    </assemblyBinding> 
</runtime> 

确保共享组件不沿着主可执行文件存在,或者它会从那里,而不是加载它们,并默默地将停止DLL文件正在内存共享所有的应用程序域之间。

然后,对于每个加载项的AppDomain,我们对其进行了配置,使得基本路径位于加载项文件夹和共享文件夹之上的文件夹,并设置了私有bin路径,以便搜索了正确的子文件夹正确的顺序:

var basePath = @"[PathToApplication]\AddIns"; 

var configFile = Path.Combine(
     basePath, 
     addInFolder, 
     addInAssemblyName + ".dll.config"); 

var binPaths = new [] { "[SharedAssemblyFolder]", addInFolder }; 

setup = new AppDomainSetup 
{ 
    ApplicationBase = basePath, 
    ConfigurationFile = configFile, 
    LoaderOptimization = LoaderOptimization.MultiDomain, 
    PrivateBinPath = string.Join(";", binPaths), 
    PrivateBinPathProbe = string.Empty, 
}; 

这样,它始终搜索共享文件夹第一,所以即使外接提供了它会被忽略的同名自己的DLL。

我们在应用程序入口点上设置了[System.LoaderOptimization(LoaderOptimization.MultiDomain)]并验证了这些DLL实际上在内存中共享(很容易让它稍微错误并且默默停止这种情况发生)。

希望这有助于某种方式。