2

过去,我编写了一个 C# 库来与 OpenOffice 一起使用,它在 Windows 中运行良好,而不是在带有 Mono 的 Ubuntu 下运行。
该库的一部分在此处作为已接受的答案发布。
这几天我发现 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 中注册)。

控制台应用程序

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;
            }
        }
    }
}

但我看不到“开始”
如果我在应用程序上评论 using(...) ,我会在控制台上看到一行...所以我认为 DLL 有问题。我"Entering Init()"在 Init() 上看不到消息。未安装 LibreOffice 和安装 LibreOffice 时的行为是相同的!!!try..catch块未执行...
我开始认为mono找不到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);
    }
}

现在在控制台中我可以看到

开始

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

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

4

3 回答 3

6

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

未处理的异常:System.TypeLoadException:发生类型加载异常。
[错误] 致命的未处理异常:System.TypeLoadException:发生类型加载异常。

没有办法让 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 = ...处理行时,我得到了

未处理的异常: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上发布一个问题,但目前没有给出有用的答案。

于 2012-04-17T19:30:16.830 回答
2

通常 Mono 会告诉我们哪个库不能加载

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

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

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

于 2012-04-15T16:39:34.160 回答
1

虽然不容易弄清楚,但这个“类型加载异常”错误可能与您的 linux 机器上缺少的包有关。

在这篇文章中查看我的答案

于 2013-08-26T13:43:59.267 回答