未找到已部署应用程序的 MEF 部件,但在调试模式下找到

Posted

技术标签:

【中文标题】未找到已部署应用程序的 MEF 部件,但在调试模式下找到【英文标题】:MEF Parts not found for deployed app, but found in Debug mode 【发布时间】:2015-07-15 10:37:26 【问题描述】:

我在这里检查了很多 MEF 问题,但我无法想象我的问题是什么。以下是正在发生的事情:

我有一个使用 AdvancedInstaller 部署的桌面 WPF 应用程序。我使用 .NET 4.0 和 MEF 组成部分。有些部分在主项目中,所以它们在 app.exe 文件中。其他部分位于引用主项目的类库中,因此它们位于 somename.dll 文件中。

问题: 从 VS 运行应用程序时,无论是在 Debug 还是在 Release 中,一切都很好。部署应用程序后,一些 dll 说它们没有要导出的部分(零)。

我检查了以下内容:

部署中的所有 dll 都可用,并且目录正在查找文件 导出类型和名称是正确的,毕竟在 Visual Studio 中一切正常 当我尝试从 dll 中添加部件时,我发现部件数量仅在部署时为零。

这是在已部署应用中找不到的代码:

var catalog = new AggregateCatalog();
string path = Environment.CurrentDirectory.ToString();
DirectoryCatalog qualitycontrol = new DirectoryCatalog(".", "QualityControl.exe"); //this is my main assembly
DirectoryCatalog qualitymix;

catalog.Catalogs.Add(qualitycontrol); //this finds the parts and always works fine

if (File.Exists(path + @"\QualityMix.dll"))

    qualitymix = new DirectoryCatalog(".", "QualityMix.dll"); //the file exists in the deployment
    catalog.Catalogs.Add(qualitymix); //the "qualitymix" catalog shows more than 20 parts if run with VS, but 0 parts in deployment

唯一有效的(但启动应用程序很慢)如下:

var catalog = new DirectoryCatalog(".", "*");

问题是它需要检查工作目录中存在的 100 多个文件,并且我无法将插件 dll 部署到不同的目录中。

为什么查看所有文件的 DirectoryCatalog 会找到部分,而查看单个部分的 DirectoryCatalog 却找不到?如果仅在已部署的应用中发生此问题,我该如何调试?

---编辑:这个问题只发生在某些 dll 上,文件被找到,而其他 dll 的部分也被找到。我在所有 dll 中使用相同的导出/导入过程,但不知何故,其中一些在部署中没有显示任何部分

您可以提出的任何建议都会有所帮助,谢谢你们!


新信息!

我尝试使用 AssemblyCatalog 加载我的 dll。它适用于 Visual Studio(调试和发布),但部署时出现以下错误:

第一次尝试:

if (File.Exists(path + @"\QualityMix.dll"))
                               
        qualitymix = new AssemblyCatalog(Assembly.LoadFile(path + @"\QualityMix.dll")); //file is loaded and parts found in VS

         catalog.Catalogs.Add(qualitymix);
    

错误:该模块应包含程序集清单。 (HRESULT 异常:0x80131018)。

第二次尝试:

 if (File.Exists(path + @"\QualityMix.dll"))
    
        var name = AssemblyName.GetAssemblyName(path + @"\QualityMix.dll");
        qualitymix = new AssemblyCatalog(Assembly.Load(name));

        catalog.Catalogs.Add(qualitymix);
    

错误:无法加载文件或程序集“QualityMix.dll”或其依赖项之一。试图加载格式不正确的程序。

我一直在寻找有关这些错误的问题,但到目前为止没有任何帮助。所有项目都是为所有 CPU 构建的,并且引用看起来没问题(这个 dll 使用与其他正在加载的项目相同的引用)。


编辑 2:

我尝试了@SuryaBhaskar 的建议,使用 LoadFrom 而不是 Load

 if (File.Exists(path + @"\QualityMix.dll"))
    
        qualitymix = new AssemblyCatalog(Assembly.LoadFrom(path + @"\QualityMix.dll"));

        catalog.Catalogs.Add(qualitymix);
    

但我得到同样的错误:无法加载文件或程序集“QualityMix.dll”或其依赖项之一。试图加载格式不正确的程序。

【问题讨论】:

Environment.CurrentDirectory 是您在部署的应用程序中所期望的吗?检查两种情况下返回的内容 感谢@VMaleev 的建议。 CurrentDirectory 很好,找到 dll 文件正常。 我试过这个解决方案无济于事:***.com/questions/9119224/… 也许它正在从另一个位置(GAC 或 AppDomain.BaseDirectory)加载 QualityMix.dll。作为最后的手段,您可以尝试运行 Process Monitor 并查看它尝试从哪个位置加载文件。 感谢@TedyPranolo,但所有 dll 都是从应用程序的安装文件夹中加载的(它是 WPF,我不使用 GAC)。为了确保没有权限问题,我将它安装在 Documents 文件夹中。 【参考方案1】:

我设法通过将有问题的 dll 的代码移动到一个新项目来解决这个问题。这解决了这个问题,不知何故......虽然原因对我来说仍然是一个谜。

【讨论】:

【参考方案2】:

使用 LoadFrom 代替 LoadFile 或 Load。如果使用 Load,它将与当前 AppDomain 上的其他程序集发生冲突

【讨论】:

感谢您的回答。请提供您提出的解决方案的代码示例以获得投票。 container.ComposeParts(); var assembly = aggregateCatalog.Parts.Select(part => ReflectionModelServices.GetPartType(part).Value.Assembly).Distinct().ToList(); foreach (Assembly dll in assembly) //根据条件将您的程序集加载到正确的程序集变量 assmbly = Assembly.LoadFrom(dll.Location); 感谢@SuryaBhaskar,但您应该编辑您的答案,以便所有人都能轻松看到。您的答案越好,您将获得更多的选票。我会试试你的方法并告诉你。 最好的方法是获取问题中的代码示例,并使用您提出的解决方案对其进行修改。这将使您获得最多的选票,因为每个人都更容易理解并表明您愿意给出一个好的答案。 我已经尝试过你的方法,但我得到了与使用 qualitymix = new AssemblyCatalog(Assembly.Load(name)); 时相同的错误

以上是关于未找到已部署应用程序的 MEF 部件,但在调试模式下找到的主要内容,如果未能解决你的问题,请参考以下文章

在发布时部署 UWP:错误 0xC0000139:未找到入口点

基于 MVC4 MEF 的动态加载插件

iOS 8 Widget Ad Hoc 分发

如何在 Android Studio 中为 Flutter 上的小部件测试进入调试模式?

MEF:“可组合部件应包含至少一个导出”

字体在发布模式下未正确呈现,但在 ASP NET Webforms 中的调试模式下工作