Mono-LibreOffice System.TypeLoadException
在过去,我编写了一个C#库来与OpenOffice一起工作,这在Windows中比在Mono下使用Ubuntu都好。
该图书馆的部分内容已发布here作为公认的答案。
在这些日子里,我发现Ubuntu决定迁移到LibreOffice,所以我尝试使用LibreOffice最新稳定版本的库。
虽然在Windows下它的正常使用,Linux下我收到此错误:Mono-LibreOffice System.TypeLoadException
Unhandled Exception: System.TypeLoadException: A type load exception has occurred.
[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeLoadException: A type load exception has occurred.
通常单告诉我们哪些库无法加载,这样我就可以安装正确的包装,一切都OK,但在这种情况下,我真的不知道发生了什么坏事。
我使用的是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的组件使用框架2.0(我认为)。
如何找到此错误的原因来解决它?
由于
UPDATE:
与框架2.0问题即使编译(如预期)是相同的。
问题(我认为)是单声道没有找到cli-uno-bridge
包(可安装在以前的Ubuntu发布,现在标记为取代),但我不能确定。
更新2:
我创建了一个测试控制台应用程序在Windows上引用CLI-UNO的DLL(它们被登记在GAC_32和GAC_MSIL)。
控制台应用程序
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
块...
我开始认为单找不到LibreOffice的CLI库...
我用updatedb
然后locate
找到他们,但我总是得到一个空的结果;我不明白,在Windows上一切正常......
更新3:
汉斯评论之后,我刚刚删除一切,但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);
}
}
,现在在控制台我能看到
Starting
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'cli_uretypes, Version=1.0.8.0, Culture=neutral, PublicKeyToken=ce2cb7e279207b9e' or one of its dependencies.
这不解决我的问题,而是帮助!
问题是:为什么LibreOffice的Linux安装(安装包+ SDK)不安装这个库?
我终于回答了我的问题,但是我想感谢@Hans帮助我找到隐藏的问题。
正如我写的,试图运行使用的LibreOffice单一个简单的应用程序,我得到这个错误
Unhandled Exception: System.TypeLoadException: A type load exception has occurred.
[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeLoadException: A type load exception has occurred.
有没有办法让单告诉我,这是错误,也不是我的应用程序在写什么安慰所以我可以理解哪个部分/行会引发错误。
在汉斯回答款给我引路
所以,当我宣布
private XComponentContext context;
private XMultiServiceFactory service;
private XComponentLoader component;
private XComponent doc;
单尝试找到正确的在执行应用程序引用的程序,而不是当这些线路将被处理!考虑到这一点,我决定继续努力。
所以我删除变量的声明和使用:
//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 = ...
被处理我
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'cli_uretypes, Version=1.0.8.0, Culture=neutral, PublicKeyToken=ce2cb7e279207b9e' or one of its dependencies.
所以我终于找到了问题:Ubuntu 11.10中的LibreOffice没有安装CLI interface package
,这个软件包已经从当前的Ubuntu发行版中剥离出来。
即使我试图手动安装其他较旧的软件包,即使转换某些rpm软件包,我也无法将Mono使用LibreOffice。
太糟糕了,即使因为之前使用OpenOffice进行分发,有cli-uno-bridge
包正在执行此项工作。希望未来能有更好的发展......
我也试过在AskUbuntu上发布一个问题,但目前没有给出有用的答案。
Usually Mono tells us which library can't load
这不是问题,它找到了一个正确名称的程序集。问题出在组件的内容。您使用的参考装配中存在的类型实际上并不存在于运行时找到的装配中。如果您在Windows上构建并在Linux上运行,发生这种情况的可能性相当不错。它应该通过给组件一个不同的[AssemblyVersion]来防止,但是有时这个规则会被忽略。微软就是这样做的。
异常的InnerException应该告诉你什么类型丢失。您可以通过反向工作来解决这个问题,使用在Linux机器上找到/安装的LibreOffice程序集作为参考程序集,因此您知道参考程序和运行时程序集之间存在匹配。缺少类型的编译错误现在很可能。如果缺少的类型不是在你的程序中直接引用,而是存在于辅助程序集中,那么你就有更大的问题。
更新:小心从你的Init()方法得出结论。 TypeLoadException在将IL编译为机器码时由抖动产生。 .NET框架有一个真正的即时编译器。单声道不,它有一个AOT(前面的时间)编译器。换句话说,它积极编译程序集中的所有代码,而不仅仅是要执行什么。因此,由于程序集中的其他代码而不是Init()中的代码,可能会引发异常。
刚刚发布自己的答案,如果没有人来了一个更好的。 – 2012-04-16 12:51:11
@HansPassant:你为什么删除你的答案?它帮助了我很多,并有很多良好的知识海事组织... – Marco 2012-04-16 13:09:58
呃,没有人投票它有帮助,你更新了问题,包括答案。我会保存它的另一个问题:) – 2012-04-16 13:23:09