【问题标题】:Mono-LibreOffice System.TypeLoadExceptionMono-LibreOffice System.TypeLoadException
【发布时间】:2012-04-19 06:04:30
【问题描述】:

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

控制台应用

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 有问题。我在 Init() 上看不到 "Entering 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,版本 = 1.0.8.0,文化 = 中性, PublicKeyToken=ce2cb7e279207b9e' 或其依赖项之一。

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

【问题讨论】:

  • 如果没有人提出更好的答案,请发布您自己的答案。
  • @HansPassant:你为什么删除你的答案?它帮助了我很多,并且是海事组织的大量知识......
  • 嗯,没有人认为它有帮助,您更新了问题以包含答案。我会把它留到另一个问题:)
  • @HansPassant:不,你在我投票之前删除了你的答案:) 真的,正是你的答案让我改变了我的代码并找到了真正的问题......你的答案并没有直接解决我的问题麻烦,但帮助我发现了隐藏的问题。所以,如果在明天之前没有人提供更好的答案,我很高兴奖励你。你是这里的大师,所以决定什么更好..我会从中学习!! :)
  • @HansPassant:这是我的第一个赏金,我没有答案......我该怎么办?谢谢

标签: c# mono ubuntu-11.10 libreoffice


【解决方案1】:

我终于回答了我的问题,但我要感谢 @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,版本 = 1.0.8.0,文化 = 中性, PublicKeyToken=ce2cb7e279207b9e' 或其依赖项之一。

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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • 我仍然认为它无法加载程序集并且我无法发现是哪一个。看看我编辑的问题。谢谢你的帮助汉斯,我真的很感激!
    • 我的问题的第三次更新。谢谢汉斯,你帮了我很多!
    • 如果我没有得到更好的答案,我正在考虑用赏金积分奖励你。以后在你看来我应该怎么做?问另一个关于 SO 的新更新的详细问题?还是转到AskUbuntu?要不然是啥?谢谢
    【解决方案3】:

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

    看我的回答on this post

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多