2

過去に、OpenOffice で動作する C# ライブラリを作成しましたが、これは 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 を使用しているためです (私はそう思います)。

このエラーの理由を見つけて解決するにはどうすればよいですか?
ありがとう

更新:
フレームワーク 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がインストールされていない場合とインストールされている場合の動作は同じです!!! try..catchブロックが実行されていません...
mono は LibreOffice CLI ライブラリを見つけることができないと思い始めました...
と を使用updatedblocateてそれらを見つけましたが、常に空の結果が得られます。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' またはその依存関係の 1 つを読み込めませんでした。

これは私の問題を解決しませんが、役立ちます!!
質問: LibreOffice の Linux インストール (インストール パッケージ + SDK) でこのライブラリがインストールされないのはなぜですか?

4

3 に答える 3

6

最後に質問に答えますが、隠れた問題を見つけるのを手伝ってくれた @Hans に感謝します。
私が書いたように、LibreOfficeを使用してMonoで簡単なアプリを実行しようとすると、このエラーが発生しました

未処理の例外: System.TypeLoadException: 型の読み込み例外が発生しました。
[エラー] FATAL UNHANDLED EXCEPTION: 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' またはその依存関係の 1 つを読み込めませんでした。

そのため、最終的に問題を見つけることができました。Ubuntu 11.10 の LibreOffice はインストールされずCLI interface package、このパッケージは現在の Ubuntu ディストリビューションから削除されました。
他の古いパッケージを手動でインストールしようとしても、いくつかの rpm パッケージを変換しても、Mono で LibreOffice を使用できませんでした。
残念ながら、OpenOffice を使用した以前のディストリビューションではcli-uno-bridge、このジョブを実行するパッケージがありました。将来的にはうまくいくことを願っています...私もAskUbuntu
に 質問を投稿しようとしましたが、現時点では有用な回答はありませんでした。

于 2012-04-17T19:30:16.830 に答える
2

通常、Monoはどのライブラリをロードできないかを教えてくれます

それは問題ではありません、それは正しい名前のアセンブリを見つけました。問題は、アセンブリの内容にあります。使用した参照アセンブリに存在していたタイプは、実行時に検出されたアセンブリには実際には存在しません。Windowsでビルドし、Linuxで実行している場合、これが発生する可能性はかなり高くなります。アセンブリに別の[AssemblyVersion]を指定することで防止できるはずですが、そのルールが無視されることがあります。たとえば、Microsoftはそうしました。

例外のInnerExceptionは、どのタイプが欠落しているかを示します。逆方向に作業することで解決できます。Linuxマシンで見つけた/インストールしたLibreOfficeアセンブリを参照アセンブリとして使用すると、参照アセンブリとランタイムアセンブリが一致していることがわかります。欠落しているタイプのコンパイルエラーが発生する可能性があります。欠落しているタイプがプログラムで直接参照されていないが、ヘルパーアセンブリに存在する場合は、より大きな問題が発生します。

更新:Init()メソッドから結論を引き出すように注意してください。TypeLoadExceptionは、ILをマシンコードにコンパイルするときにジッターによって生成されます。.NET Frameworkには、真のジャストインタイムコンパイラがあります。Monoにはありません。AOT(Ahead Of Time)コンパイラがあります。つまり、実行しようとしているコードだけでなく、アセンブリ内のすべてのコードを積極的にコンパイルします。したがって、Init()内のコードだけでなく、アセンブリ内の他のコードが原因で例外が発生する可能性があります。

于 2012-04-15T16:39:34.160 に答える
1

把握するのは簡単ではありませんが、この「type load exception」エラーは、Linux マシンでパッケージが見つからないことに関連している可能性があります。

この投稿で私の答えを見てください

于 2013-08-26T13:43:59.267 に答える