Mono-LibreOffice System.TypeLoadException

在过去,我编写了一个C#库来使用OpenOffice,这在Windows中比在Ubuntu下使用Mono更好。
此库的一部分在此处作为已接受的答案发布。
在这些日子里,我发现Ubuntu决定转移到LibreOffice,所以我尝试使用LibreOffice最新的稳定版本。
虽然在Windows下它运行良好,但在Linux下我收到此错误:

Unhandled Exception: System.TypeLoadException: A type load exception has occurred. [ERROR] FATAL UNHANDLED EXCEPTION: System.TypeLoadException: A type load exception has occurred. 

通常Mono告诉我们哪个库无法加载,所以我可以安装正确的包,一切都很好,但在这种情况下,我真的不知道什么是坏的。

我正在使用Ubuntu oneiric ,我的库是用Framework 4.0编译的。
在Windows下我必须将其写入app.config:

       

因为LibreOffice程序集使用Framework 2.0(我认为)。

如何找到解决此错误的原因?
谢谢

更新:
即使使用Framework 2.0问题进行编译(如预期的那样)也是如此。
问题(我认为)是Mono没有找到cli-uno-bridge软件包(可以在以前的Ubuntu版本上安装,现在标记为取代),但我不能确定。

更新2:
我在Windows上创建了一个引用cli-uno dll的测试控制台应用程序(它们在GAC_32和GAC_MSIL中注册)。

CONSOLE应用程序

 static void Main(string[] args) { Console.WriteLine("Starting"); string dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string doc = Path.Combine(dir, "Liberatoria siti web.docx"); using (QOpenOffice.OpenOffice oo = new QOpenOffice.OpenOffice()) { if (!oo.Init()) return; oo.Load(doc, true); oo.ExportToPdf(Path.ChangeExtension(doc, ".pdf")); } } 

图书馆:

 using unoidl.com.sun.star.lang; using unoidl.com.sun.star.uno; using unoidl.com.sun.star.container; using unoidl.com.sun.star.frame; using unoidl.com.sun.star.beans; using unoidl.com.sun.star.view; using unoidl.com.sun.star.document; using System.Collections.Generic; using System.IO; using System; namespace QOpenOffice { class OpenOffice : IDisposable { private XComponentContext context; private XMultiServiceFactory service; private XComponentLoader component; private XComponent doc; public bool Init() { Console.WriteLine("Entering Init()"); try { context = uno.util.Bootstrap.bootstrap(); service = (XMultiServiceFactory)context.getServiceManager(); component = (XComponentLoader)service.createInstance("com.sun.star.frame.Desktop"); XNameContainer filters = (XNameContainer)service.createInstance("com.sun.star.document.FilterFactory"); return true; } catch (System.Exception ex) { Console.WriteLine(ex.Message); if (ex.InnerException != null) Console.WriteLine(ex.InnerException.Message); return false; } } } } 

但是我无法看到“正在开始” !!!
如果我在应用程序上使用(…)进行评论,我会在控制台上看到一行…所以我认为它在DLL中出错了。 在那里,我无法在Init()上看到"Entering Init()"消息。 未安装LibreOffice时的行为是相同的!!! try..catch块未执行…
我开始认为mono无法找到LibreOffice CLI库…
我使用updatedb然后locate它们,但我总是得到一个空的结果; 我不明白,在Windows上一切正常……

更新3:
在Hans评论之后,我刚刚删除了我的库中除Init()所有内容,但错误仍然存​​在。 所以我感动了

 //private XComponentContext context; //private XMultiServiceFactory service; //private XComponentLoader component; //private XComponent doc; //private List filters = new List(); #region Constructors public OpenOffice() { Console.WriteLine("Entering Init()"); try { var context = uno.util.Bootstrap.bootstrap(); var service = (XMultiServiceFactory)context.getServiceManager(); var component = (XComponentLoader)service.createInstance("com.sun.star.frame.Desktop"); } catch (System.Exception ex) { Console.WriteLine(ex.Message); if (ex.InnerException != null) Console.WriteLine(ex.InnerException.Message); } } 

现在在控制台我能看到

开始

未处理的exception:System.IO.FileNotFoundException:无法加载文件或程序集’cli_uretypes,Version = 1.0.8.0,Culture = neutral,PublicKeyToken = ce2cb7e279207b9e’或其依赖项之一。

这不能解决我的问题,但有帮助!!
问题是:为什么LibreOffice的Linux安装(安装包+ SDK)没有安装这个库?

我终于回答了我的问题,但我要感谢@Hans帮助我找到隐藏的问题。
正如我写的那样,尝试使用LibreOffice运行一个简单的Mono应用程序,我收到了这个错误

未处理的exception:System.TypeLoadException:发生了类型加载exception。
[ERROR]致命的UNHANDLED EXCEPTION:System.TypeLoadException:发生了类型加载exception。

没有办法让Mono告诉我哪个是错误,我的应用程序也没有写任何东西到控制台,所以我可以理解哪个部分/行引发了错误。
汉斯回答中的一段显示了我的方式

.NET框架具有真正的即时编译器。 Mono没有,它有一个AOT(Ahead Of Time)编译器。 换句话说,它积极地编译程序集中的所有代码,而不仅仅是要执行的代码。

所以当我宣布时

 private XComponentContext context; private XMultiServiceFactory service; private XComponentLoader component; private XComponent doc; 

Mono尝试在执行应用程序时找到引用的程序集,而不是在处理这些行时! 想到这一点,我决定继续前进。
所以我删除了变量声明并使用了:

 //private XComponentContext context; //private XMultiServiceFactory service; //private XComponentLoader component; var context = uno.util.Bootstrap.bootstrap(); var service = (XMultiServiceFactory)context.getServiceManager(); var component = (XComponentLoader)service.createInstance( "com.sun.star.frame.Desktop"); 

再次执行我的应用程序,我能够看到我期望的控制台消息,最后,当我处理了行var context = ...

未处理的exception:System.IO.FileNotFoundException:无法加载文件或程序集’cli_uretypes,Version = 1.0.8.0,Culture = neutral,PublicKeyToken = ce2cb7e279207b9e’或其依赖项之一。

所以我终于找到了问题:Ubuntu 11.10中的LibreOffice没有安装CLI interface package ,这个包已经从当前的Ubuntu发行版中删除了。
即使我尝试手动安装其他较旧的软件包,甚至转换一些rpm软件包,我也无法将LibreOffice与Mono一起使用。
太糟糕了,即使因为先前使用OpenOffice进行分发,也有cli-uno-bridge软件包完成这项工作。 希望将来更好……
我也尝试在AskUbuntu上发帖提问,但目前没有给出有用的答案。

通常Mono告诉我们哪个库无法加载

这不是问题,它找到了一个名字正确的程序集。 问题在于assembly的内容 。 您使用的引用程序集中存在的类型实际上并不存在于它在运行时找到的程序集中。 如果您在Windows上构建并在Linux上运行,那么发生这种情况的可能性非常大。 它应该通过给程序集提供不同的[AssemblyVersion]来防止,但有时会忽略该规则。 微软就是这么做的。

exception的InnerException应该告诉你缺少什么类型。 您可以通过向后工作来解决它,使用在Linux机器上找到/安装的LibreOffice程序集作为引用程序集,这样您就可以知道引用和运行时程序集之间存在匹配。 现在可能存在缺失类型的编译错误。 如果缺少的类型没有在程序中直接引用但存在于帮助程序集中,那么您就会遇到更大的问题。

更新:小心从Init()方法中得出结论。 TypeLoadException是在将IL编译为机器代码时由抖动生成的。 .NET框架具有真正的即时编译器。 Mono没有,它有一个AOT(Ahead Of Time)编译器。 换句话说,它积极地编译程序集中的所有代码,而不仅仅是要执行的代码。 因此,由于程序集中的其他代码而不仅仅是Init()中的代码,可能会引发exception。

尽管不容易弄清楚,这种“类型加载exception”错误可以链接到linux机器上缺少的包。

请参阅我在这篇文章中的回答