3

COM shim ウィザードを使用して Word 共有アドインを開発しています。 http://blogs.msdn.com/b/mshneer/archive/2010/03/19/com-shim-wizards-for-vs-2010.aspx

いくつかのスレッドを使用しようとするまで、すべてがうまくいきました。一部のマシンでは、メイン スレッドで作成された COM オブジェクトの TYPE_E_LIBNOTREGISTERED 例外で失敗します。

Word イベントから Word ドキュメント オブジェクト (_doc) を取得し、次のように STA スレッドから使​​用しようとしています。

Word.Document _doc;
void Start()
{
    _mainLoopThread = new Thread(MainLoop);
    _mainLoopThread.SetApartmentState(ApartmentState.STA);
    _mainLoopThread.IsBackground = true;
    _mainLoopThread.Start();
}
void MainLoop()
{
    // some code...
    Word.Range r = _doc.StoryRanges[Word.WdStoryType.wdMainTextStory];
    // some code...
}

私の開発マシン、テスト マシン、およびほとんどのユーザーですべてが正常に動作します。ただし、一部のユーザーは例外で失敗します: 型 'Microsoft.Office.Interop.Word.DocumentClass' の COM オブジェクトをインターフェース型 'Microsoft.Office.Interop.Word._Document' にキャストできません。IID '{0002096B-0000-0000-C000-000000000046}' を持つインターフェイスの COM コンポーネントでの QueryInterface 呼び出しが次のエラーにより失敗したため、この操作は失敗しました: ライブラリが登録されていません。(HRESULT からの例外: 0x8002801D (TYPE_E_LIBNOTREGISTERED))。

再現できた唯一の方法は、Office 2013 をインストールしてから削除し、Office 2007 をインストールすることです。レジストリを確認しましたが、この GUID の登録に関する問題は見つかりませんでした。Office 2013 の残り物をクリアする必要がある MS のツールを試してみ ましたが、役に立ちませんでした。

エラーなしでメインスレッドから同じ _doc オブジェクトを使用できるため、これは登録の問題ではありません。COM-shim の rgs-file では、STA モデルを使用します。

ここで提案されているように、CoMarshalInterThreadInterfaceInStream を使用しようとしまし た。他の STA スレッドから STAThread から作成された COM オブジェクトを呼び出すことはできません が、私の開発マシンでも機能させることができませんでした。コードは次のとおりです。

    IStream _docForThreadStream = null;

    Guid _docInterfaceGuid;

    void InitDocForThread()
    {            
        object[] attr = _doc.GetType().GetCustomAttributes(typeof(GuidAttribute), false);
        GuidAttribute g = (GuidAttribute)attr[0];
        _docInterfaceGuid = new Guid(g.Value);

        CoMarshalInterThreadInterfaceInStream(ref _docInterfaceGuid, Marshal.GetIUnknownForObject(_doc), out _docForThreadStream);
    }

    [DllImport("ole32.dll")]
    static extern int CoGetInterfaceAndReleaseStream(IStream pStm, [In] ref Guid riid, out object ppv);

    Word.Document _docForThread = null;

    void MainLoop()
    {
            object pDoc;
            int hr = CoGetInterfaceAndReleaseStream(_docForThreadStream, ref _docInterfaceGuid, out pDoc);
            // _docForThreadStream != null, hr == E_NOINTERFACE
     }

CoGetInterfaceAndReleaseStream は、IStream からオブジェクトを取得しようとすると E_NOINTERFACE を返します。誰でもC#の作業例のリンクを送ってもらえますか? 私はグーグルで検索しましたが、C++ の例はいくつかしか見つかりませんでした。

Office COM 登録は、同じスレッド (オフィスと同じスレッドで実行されているアドイン) で機能するように破損しているようですが、別の STA スレッドへのマーシャリングに失敗しています...

4

1 に答える 1

-1

つい最近、スレッドでWordオブジェクトモデルを呼び出すときに、まったく同じケースであるTYPE_E_LIBNOTREGISTEREDを確認しました。メインスレッドでのみOfficeオブジェクトモデルを使用する必要があります。http://www.add-in-express.com/creating-addins-blog/2010/11/04/threads-managed-office-extensions/で、いくつかの情報とその他のリンクを見つけてください

于 2012-12-05T14:38:27.860 に答える