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 スレッドへのマーシャリングに失敗しています...