【问题标题】:MEF loading plugins from a network shared folderMEF 从网络共享文件夹加载插件
【发布时间】:2011-11-09 10:46:04
【问题描述】:

撕扯我的头发试图找出我为什么会遇到这个问题,所以希望有人能提供帮助。

我有一个使用 MEF 加载插件的程序。我希望系统的客户端和服务器部分能够使用位于服务器上的相同插件存储。

我的问题是,当我将插件位置设置为“C:\Users\Administrator\Desktop\ClientPlugins”时,插件加载正常。如果我将位置更改为“\\XRP-SERVER\Users\Administrator\Desktop\ClientPlugins”,则不会加载插件。

当我在 Windows 资源管理器中输入“\\XRP-SERVER\Users\Administrator\Desktop\ClientPlugins”时,找到了位置并且插件 dll 就在那里。

请有人帮忙。

如果您需要更多信息,请告诉我。

根据建议,我尝试编辑配置以包含以下内容,但这并没有解决问题....

  <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <runtime>
        <loadFromRemoteSources enabled="true"/>
      </runtime>

亲切的问候

【问题讨论】:

    标签: c# mef


    【解决方案1】:

    安全策略通常会禁止加载远程代码(即外部位置的程序集)。

    您可以尝试以下配置更改:

    <runtime>
        <loadFromRemoteSources enabled="true"/>
    </runtime>
    

    要注意的另一件事是,当您从网络位置复制文件时,它们通常会在其备用数据流中指定一个区域。在资源管理器中,可以在查看文件属性时使用“取消阻止”命令来删除它。

    或者,您可以通过编程方式从备用数据流中删除区域,如 here on Mike Hadlow's blog 所示。

    【讨论】:

    • 当我看到这个时,我的眼睛亮了起来,因为我认为它会起作用。看起来它已经完成了:(我已经将它放在配置中,并且在使用'\\XRP-SERVER\Users\Administrator\Desktop\ClientPlugins'路径时它仍然不会加载。还有其他想法吗?
    【解决方案2】:

    我昨天遇到了这个问题,并将问题缩小到 MEF 如何加载程序集。 创建 DirectoryCatalog 时,它会依次创建 AssemblyCatalog 集合。 每个 AssemblyCatalog 都会:

        AssemblyName assemblyName = AssemblyName.GetAssembly();
        Assembly.Load(assemblyName);
    

    Assembly.Load 的调用会引发沙箱异常(原因我还无法解释),因此没有找到任何部分,因为它会默默地捕获错误。

    有趣的是,调用Assembly.LoadFrom(&lt;pathToYourDll&gt;) 以返回Assembly 工作正常(不会引发异常)。将其与AssemblyCatalog 的重载构造函数结合起来,该构造函数将Assembly 作为其输入,您就有了一个解决方法!

    因此,我没有使用DirectoryCatalog,而是列出了路径中的所有DLL,并反复创建AssemblyCatalog并将其添加到我的CompositionContainer

    注意:我在 App.Config 中使用 loadFromRemoteSources="true" 标志,它是必需的,否则它总是崩溃。

    希望对你有帮助

    【讨论】:

    • 我正在尝试此操作,直到您将 AssemblyCatalog 添加到 CompositionContainer 为止。我在 CompositionContainer 上看不到添加方法。请您再解释一下好吗?
    • 没关系,我发现您需要创建一个 aggregateCatalogue,然后将您的 assemblyCatalogues 添加到其中,然后将您的 aggregateCatalogue 添加到 compositionContainer 中。
    • 请告诉我,如果您知道为什么这有效而标准方法无效 :) 我敢说微软也会有兴趣知道 :) 再次感谢您的回答 :)
    • 我查看了 Reflector 但找不到原因。我想这与 Load 和 LoadFrom 之间的上下文差异有关(请参阅here)。自从我上次回答以来,我还发现 LoadFrom 可能很危险,我遇到了这个问题here:使用 LoadFrom 加载两次相同的 DLL 可能会导致奇怪的行为。如果你要使用 LoadFrom,你必须严格:)
    【解决方案3】:

    只是为了澄清 sebd 的答案有效。

    这是我使用的最终代码。

    string[] files = Directory.GetFiles(ClientPluginStore, "*.dll", SearchOption.TopDirectoryOnly);
    
    AggregateCatalog aggCat = new AggregateCatalog();
    
    aggCat.Catalogs.Add(catalog);
    
    foreach ( string file in files )
    {
        Assembly ass = Assembly.LoadFrom(file);
    
        AssemblyCatalog assCat = new AssemblyCatalog(ass);
    
        aggCat.Catalogs.Add(assCat);
    }
    
    _container = new CompositionContainer(aggCat);
    

    【讨论】:

      【解决方案4】:

      尝试使用 System.IO.Path.PathSeparator 代替 \?

      或者可以先将文件获取到客户端位置?

      我不太确定,但我会试一试。

      【讨论】:

      • 谢谢,我试试路径分隔符。如果客户端无权访问共享位置,未来的任务是通过 wcf 从服务器流式传输插件。我想首先让共享位置工作,并想了解它为什么不工作:)
      • 另一件事是,当我想到它时:使用“file://”?
      • 我已经检查过我是否以 C# 可以读取的格式提供路径。 int fCount = Directory.GetFiles("\\\\XRP-SERVER\\Users\\Administrator\\Desktop\\ClientPlugins", ".", SearchOption.TopDirectoryOnly).Length; Console.WriteLine(fCount);这将返回 1,即插件 dll
      • 那么,反斜杠就是答案?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多