托管可扩展性框架(MEF)和托管AddIn框架(MAF,又名System.AddIn)似乎完成了非常类似的任务.根据这个Stack Overflow问题,MEF是System.Addin的替代品吗?,你甚至可以同时使用两者.
你什么时候选择使用一个与另一个?在什么情况下你会选择同时使用它们?
我正在寻找一种从.NET应用程序访问插件的简单而安全的方法.虽然我认为这是一个非常普遍的要求,但我很难找到满足我所有需求的东西:
我已经调查了MEF和MAF,但我很难看到如何使它们中的任何一个符合要求.
假设我的理解是正确的,MAF无法支持在其隔离边界上传递泛型类型,这对我的应用程序至关重要.(MAF实现起来也非常复杂,但如果我能解决泛型问题,我会准备好使用它).
MEF几乎是一个完美的解决方案,但似乎无法满足安全性要求,因为它将扩展程序集加载到与主机相同的AppDomain中,因此显然可以防止沙箱化.
我已经看到了这个问题,它讨论了在沙盒模式下运行MEF,但没有描述如何.这篇文章指出"当使用MEF时,你必须信任扩展不运行恶意代码,或通过代码访问安全提供保护",但同样,它没有描述如何.最后,有这篇文章描述了如何防止未知插件被加载,但这不适合我的情况,因为即使是合法的插件也是未知的.
我已经成功地将.NET 4.0安全属性应用于我的程序集,并且MEF正确地尊重它们,但是我没有看到这有助于我锁定恶意代码,因为许多可能是安全威胁的框架方法(例如,方法System.IO.File
)标记为SecuritySafeCritical
,这意味着它们可以从SecurityTransparent
程序集访问.我在这里错过了什么吗?是否有一些额外的步骤我可以告诉MEF它应该为插件程序集提供互联网权限?
最后,我也看了创造我自己的简单的沙盒插件架构,使用单独的AppDomain,描述在这里.但是,据我所知,这种技术只允许我使用后期绑定来调用不受信任的程序集中的类上的静态方法.当我尝试扩展这种方法来创建我的一个插件类的实例时,返回的实例无法转换为公共插件接口,这意味着主机应用程序无法调用它.是否有一些技术可用于跨AppDomain边界获得强类型代理访问?
我为这个问题的长度道歉; 原因是要显示我已经调查过的所有途径,希望有人可以提出新的尝试.
蒂姆,非常感谢你的想法
我有一个使用Popup的WPF用户控件.此控件是一个插件,可以加载到主AppDomain或单独的AppDomain中,并使用ElementHost以Winforms形式托管.当插件在主AppDomain中加载并打开弹出窗口时,弹出窗口的字段之间的选项卡会将焦点移动到弹出窗口父窗口的第一个控件.当它加载到新的AppDomain中时,选项卡行为按预期/期望的方式工作(它会循环显示弹出窗口中的控件).
我已经在SO和其他地方阅读了许多相似但不完全相同的问题,但没有一个建议有所帮助.
看来Tab键消息是在AddInHost中处理的(它来自我使用FrameworkElementAdapters来在域外情况下跨域边界编组WPF控件).我的最终目标是将其实现为托管外接程序框架插件,但我已经减少了WAY以简化repro.
如果它有助于拥有更完整的上下文,我有一个简化repro的git repo
我该怎么做才能使这种行为保持一致?
WpfUserControl.xaml
<UserControl x:Class="MyPlugin.WpfUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" Background="White">
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="28" />
<RowDefinition Height="28" />
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Margin="3" />
<Button x:Name="DropDownButton" Grid.Row="1" Margin="3" HorizontalAlignment="Left" MinWidth="100" Content="Drop Down" Click="DropDownButton_OnClick" />
<Popup Grid.Row="1" x:Name="Popup1" Placement="Right" StaysOpen="True" PlacementTarget="{Binding ElementName=DropDownButton}">
<Border BorderBrush="Black" BorderThickness="1">
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Content="Username:" Grid.Row="0" Grid.Column="0" Margin="3" />
<TextBox Grid.Row="0" Grid.Column="1" Margin="3" MinWidth="150" …
Run Code Online (Sandbox Code Playgroud) 是否可以使用MEF或MAF等容器在.net 3.5应用程序中加载.net 4.0应用程序?
我知道在.NET中只支持向后兼容性,这会对容器产生什么影响吗?
我有一个使用托管外接程序框架(MAF)的基于插件的体系结构的程序.我试图以他们自己的进程中运行的方式加载我的加载项程序集,我可以指定他们应该在哪里寻找要加载的其他程序集.以下是我尝试过的两种不同的方法以及为什么它们不能100%工作:
AppDomain _domain;
// Create application domain setup information.
AppDomainSetup domaininfo = new AppDomainSetup();
// Configure
domaininfo.ApplicationName = PluginName;
domaininfo.ApplicationBase = MyPath;
domaininfo.PrivateBinPath = MyPath;
domaininfo.LoaderOptimization = LoaderOptimization.MultiDomain;
domaininfo.DisallowApplicationBaseProbing = false;
domaininfo.DisallowBindingRedirects = false;
domaininfo.DisallowCodeDownload = false;
domaininfo.DisallowPublisherPolicy = false;
System.Security.Policy.Evidence adevidence = AppDomain.CurrentDomain.Evidence;
// Create the new application domain using setup information.
_domain = AppDomain.CreateDomain(PluginName + "_Domain", adevidence, domaininfo);
_addin = _token.Activate<IOpenSourceAutomationAddInv2>(_domain);
Run Code Online (Sandbox Code Playgroud)
此方法允许我告诉每个加载项在新的应用程序域中运行,我可以指定在哪里查找其他程序集.这很重要,因为每个加载项都在其自己的子目录中,并且需要查找与主机相同的目录以加载其他程序集.此方法的问题是,如果加载项具有未处理的异常,则会导致主机崩溃,因为它在同一进程中运行.
AddInProcess _process;
_process = new AddInProcess(Platform.AnyCpu);
_addin = _token.Activate<IOpenSourceAutomationAddInv2>(_process,AddInSecurityLevel.FullTrust);
Run Code Online (Sandbox Code Playgroud)
此方法将每个加载项加载到其自己的进程中,因此单个加载项崩溃不会影响主机.这个问题是我无法弄清楚是否可以告诉加载项在哪里寻找其他程序集.它们只会查看其目录而不是主机的目录.
使用MAF以实现我正在寻找的最佳方式是什么?我需要能够加载我的加载项是这样一种方式将它们与主机分开,因为我没有编写加载项.我无法控制他们的代码所以我需要确保他们不会崩溃主机.我还需要能够指定加载项应该加载程序集的位置,因为它们将位于它们自己的子目录中,并且需要从主机目录加载程序集.如果可能的话,我也不愿意使用GAC.
有谁知道如何处理使用System.AddIn创建的AddIns.在线的所有示例似乎都显示了如何轻松加载和使用插件,但没有一个显示如何在它们活着时处置它们.我的问题是我在新进程中创建插件,这些进程永远不会被垃圾收集,显然是一个问题.
下面是一些说明我的问题的示例代码.假设用户从不退出此应用程序,而是创建许多ICalculator实例.这些addIn进程如何处理掉?
static void Main(string[] args)
{
string addInRoot = GetExecutingDirectory();
// Update the cache files of the pipeline segments and add-ins
string[] warnings = AddInStore.Update(addInRoot);
// search for add-ins of type ICalculator
Collection<AddInToken> tokens = AddInStore.FindAddIns(typeof(ICalculatorHost), addInRoot);
string line = Console.ReadLine();
while (true)
{
AddInToken calcToken = ChooseCalculator(tokens);
AddInProcess addInProcess = new AddInProcess();
ICalculatorHost calc = calcToken.Activate<ICalculatorHost>(addInProcess, AddInSecurityLevel.Internet);
// run the add-in
RunCalculator(calc);
}
}
Run Code Online (Sandbox Code Playgroud) 我有一个.ipa文件,它是使用分发配置文件部署应用程序的输出。当我尝试在任何新的ios设备中安装IPad Mini(使用Itunes)时,安装过程将一直显示到“无法安装,请稍后再试”,直到75%。
注意:相同的.ipa文件以前可以工作4个月,但现在无法安装。我了解证书和配置文件仅对于ipa部署是必需的,但是可以在任何ios设备上完成安装而无需太多的先决条件。
我是否错过了这里的任何东西,或者IpadMini中缺少证书/配置文件之类的东西?请帮忙。
对于常规组件,可以使用MEF动态加载组件.如果这些程序集需要实时更新,建议使用AppDomain来托管动态程序集(可能可以使用托管外接程序框架(MAF)).需要更新时,将停止appdomain,更新程序集并重新加载appdomain.
那些由ASP .NET加载的包含类后面代码的程序集呢?如何在不强制重新启动主应用程序域的情况下更新它们.是否可以在动态应用程序域中托管我的一些页面?你会怎么做?这个appdomain可以共享登录令牌和身份验证的东西,这样用户就不必重新登录了吗?
谢谢
我正在使用Microsoft AddIn Framework来加载AddIn程序集.我在他们自己的进程中运行它们以将它们与服务分开.我不喜欢它,每个AddIn进程在任务管理器中显示为AddInProcess32.exe.使用进程隔离时,我们如何重命名taskmanager中显示的名称,以便为用户提供更多描述?
有没有办法缓存每个应用程序启动(WPF)的MEF组件图,就像MAF一样,以避免在每次应用程序启动时发现目录并构建组件图.为了加快我的应用程序启动速度.MAF使用AddinsStore存储所有插件,当新插件发现存储重建并再次保存时.使用MEF设计的模块化应用程序可以做到这一点吗?
编辑:
在我的项目架构中我有扩展,模块和托管服务所以我有不同的导出像(IExtension,IModule,IManagedService),我处理所有组件的开始依赖项,我想要的正是ex(扩展目录)包含许多dll并且可能并非所有dll都包含(exports/Imports),因为某些dll只引用了一些Extensions.所以MEF的默认发现行为是在Extension Directory中的所有程序集中搜索exports/Imports,但我想通过查看所有dll并捕获类型及其名称和dll以在其中使用它们来修改此行为下一个启动时间.从catch直接加载组件(Exports),以便MEF知道可用的组件及其位置,而无需加载和搜索dll.它看起来像是一个Exports及其Places和依赖项的字典,可以直接从它的地方(dll)获取实例.