过去我写了一个C#库来使用OpenOffice,这在Windows中都比在Ubuntu和Mono下都好。
该库的一部分已作为已接受的答案发布here
在这些日子里,我发现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:
<?xml version="1.0"?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/>
</startup>
</configuration>
因为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"));
}
}
LIBRARY:
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<string> filters = new List<string>();
#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);
}
}
现在在控制台中我能看到
启动
未处理的异常:System.IO.FileNotFoundException:无法加载 文件或程序集'cli_uretypes,Version = 1.0.8.0,Culture = neutral, PublicKeyToken = ce2cb7e279207b9e'或其中一个依赖项。
这不能解决我的问题,但有帮助!!
问题是:为什么LibreOffice的Linux安装(安装包+ SDK)没有安装这个库?
答案 0 :(得分:5)
我终于回答了我的问题,但我要感谢@Hans帮助我找到隐藏的问题 正如我写的那样,尝试使用LibreOffice使用Mono运行一个简单的应用程序,我得到了这个错误
未处理的异常:System.TypeLoadException:类型加载异常 发生了。
[错误]致命未处理例外情况: System.TypeLoadException:发生了类型加载异常。
没有办法让Mono告诉我哪个是错误,我的应用程序也没有写任何东西到控制台,所以我可以理解哪个部分/行引起错误。
汉斯回答中的一段显示了我的方式
.NET框架具有真正的即时编译器。它不是单声道 有一个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 = ...
时,我得到了
未处理的异常: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发帖提问,但目前没有给出有用的答案。
答案 1 :(得分:2)
通常Mono告诉我们哪个库无法加载
这不是问题,它找到了一个名称正确的程序集。问题出在程序集的内容上。您使用的引用程序集中存在的类型实际上并不存在于它在运行时找到的程序集中。如果您在Windows上构建并在Linux上运行,那么发生这种情况的可能性非常大。应该通过给程序集提供不同的[AssemblyVersion]来防止它,但有时会忽略该规则。例如,微软做了。
异常的InnerException应该告诉你缺少什么类型。您可以通过向后工作来解决它,使用在Linux机器上找到/安装的LibreOffice程序集作为引用程序集,这样您就可以知道引用和运行时程序集之间存在匹配。现在可能存在缺失类型的编译错误。如果缺少的类型没有在程序中直接引用但存在于帮助程序集中,那么您就会遇到更大的问题。
更新:小心从您的Init()方法中得出结论。 TypeLoadException是在将IL编译为机器代码时由抖动生成的。 .NET框架具有真正的即时编译器。 Mono没有,它有一个AOT(Ahead Of Time)编译器。换句话说,它积极地编译程序集中的所有代码,而不仅仅是要执行的代码。因此,由于程序集中的其他代码而不仅仅是Init()中的代码,可能会引发异常。
答案 2 :(得分:1)
虽然不容易理解,但这种“类型加载异常”错误可以链接到linux机器上缺少的包。
请参阅我的回答on this post