2009-11-23 8 views
6

IMyInterfaceを実装するCOMクラスCMyCOMServerがあり、いずれも正しいGUIDを使用しています。 CMyCOMServer::QueryInterfaceは、IUnknownまたはIMyInterfaceが要求された場合はS_OKを返し(正しいタイプにキャストします)、そうでない場合はE_NOINTERFACEを返します。同じPC上の他のアプリでインターフェイスが見つかってもE_NOINTERFACEを返すCoCreateInstance

、私が呼ん:

HRESULT hr = ::CoCreateInstance(__uuidof(CMyCOMServer), 0, CLSCTX_SERVER, 
__uuidof(IMyInterface),(void **)&pInterface); 

それはE_NOINTERFACEを返します。だから私は何か間違っていると仮定し、CMyCOMServer::QueryInterfaceにブレークポイントを追加しました。私はCoCreateInstanceが呼び出されたときに、QueryInterfaceは異なるインタフェースのための複数回トリガーされることがわかった:

  • まず、IUnknownのが要求されていない - などIMarshallのような何の問題
  • をその後、いくつかのインタフェースが要求されている...これらはサポートされていません。したがって、E_NOINTERFACEが返されます。
  • 最後に、IMyInterfaceが要求されます。呼び出しのCoCreateInstanceは私にNULLポインタとE_NOINTERFACEのリターンコードを残している理由COMサーバアプリが明確に帰国したとき

は、だから私の混乱は、ある期待通りのQueryInterfaceは、S_OKを返し、インタフェースポインタとして(IMyInterface *)thisをセットIを検証インターフェイス私は頼む?

EDIT:私のクライアントアプリケーションは起動時にCoInitialize(NULL)を呼び出しますが、これは違いはありません。

+1

明確にする:COMサーバーは1つのアプリケーションで実行され、クライアントは別のアプリケーションで実行されますか?これは、彼らが別のプロセスに入ることを意味し、それはあなたがマーシャリングする必要があることを意味します。 – MSalters

+0

はい、そうです。 PC 1台につき2つの別々のアプリ。私はマーシャルの前にぶち込まなければならなかったことはありません。それが私が混乱している理由です。私はこれまでほとんど聞いたことがなく、かなりの量のCOM開発を行ってきました。 –

答えて

5

COMサーバーが別のプロセスまたは同じプロセス内の別のアパートメントで実行されている場合、COMはインターフェイスの呼び出し時にパラメータのパッケージ化と送信方法を知る必要があります。このプロセスは「マーシャリング」と呼ばれます。

カスタムインターフェイスを定義する場合は、次のいずれかの方法を使用してカスタムインターフェイスをマーシャリングする必要があります。

  • をマーシャリング標準:あなたは、システムに登録する必要があり、プロキシ とスタブを生成するMIDLコンパイラを持っています。既にインターフェイスを定義しているので、これはおそらく最適なオプションです。
  • OLEオートメーションマーシャリング:あなたは、オートメーション互換 カスタムインターフェイスを定義し、カスタムをマーシャリングすでに COMフレームワーク
  • の一部である マーシャラーを使用する:あなたは
IMarshalのメソッドを実装

COMサーバーをデバッグしているとき、QueryInterfaceの呼び出しでカスタムインターフェイスを返すことがわかりますが、COMはそのインターフェイスをマーシャリングする方法を理解できないため、クライアントはE_NOINTERFACEを見ます。 (あなたのコメントに基づいて)

UPDATE

これは、既存のCOMサーバーアプリケーションであるなら、あなたはおそらく既に、プロキシ/スタブを持っています。これをクライアントとサーバーの両方に登録する必要があります。新しいマシンでこれをテストしていて、これを登録するのを忘れたことはありますか?登録するには、プロキシ/スタブDLLでregsvr32を実行するだけです。インターフェースが欠落しているのマーシャリングすることは非常に有用だったのでE_NOINTERFACEについて

+0

私が言ったように、サーバーアプリケーションは新しいコードではありません。ライブシステムですでに使用されています。インターフェースや何も変更はありません。サーバー側で何かを変更することは選択肢ではありません。私は、他のクライアントが何らかの形でそれを管理しているので、新しいクライアントアプリケーションをそこで動作させる必要があります。 –

+0

これは最高の答えだと思います。私たちはプロキシスタブDLLを持っていたことが分かりました。私はそれを認識していませんでした。 regsvr32を使って修正しました。 –

2

スレッドモデルの問題の可能性がありますか?Raymond Chen wrote about

コメントへの返信での編集:

あなたのスレッドモデルは、あなたが作成しているオブジェクトのスレッドモデルと互換性がない場合は、COMのマーシャリングキックINとマーシャリングのものがない場合。マーシャリング・インターフェースが欠落しているため、出てくるエラーはE_NOINTERFACEです。

これは、実際にマーシャリングよりもスレッドモデルに関するものです。

+0

多分、私はこれまでMarshallingを使用したことがなく、このプロジェクトで3年間働いた後、100以上のCOMサーバEXE/DLLを使用していることを認識しています。カスタムマーシャリングやファンスレッディングはどこにも行われません。だから今はなぜそれが問題になるのか混乱している。 –

5

これは、COMサブシステムがカスタムインターフェイス(IMyInterface)をマーシャリングしようとしているために発生します。これは、サーバーがout-procであるか、またはサーバーがin-procでCoCreateInstance()を呼び出すコンシューマーアプリケーションのスレッドがCoInitialize()/ CoInitializeEx()を誤って呼び出したために "マルチスレッドアパートメント"記事のuser Thomasは、他の答えに言及しています。

インプロセスサーバーだけが必要な場合は、CoCreateInstance()を呼び出すスレッドがCOINIT_APARTMENTTHREADEDを指定してCoInitialize()またはCoInitializeEx()を呼び出して「シングルスレッドアパートメント」を実行するようにすることでマーシャリングを抑制できます。

アウトプロセスサーバーが必要な場合は、マーシャリングを回避することはできません。あなたは、次のいずれかを行うことができ、後者の場合:

  • IMarshalを実装 -
  • 以上が好ましく、プロキシ/スタブを追加し、カスタムインターフェイス
  • (ではない、それはOUT-のために働く場合は確かにそれらを登録procですが、最も簡単です)もしあなたのインタフェースがオートメーションマーシャリングでマーシャリングできるなら、COMサーバのリソースにtyplibを組み込み、そのtypelibをレジストリに登録するだけです。
+0

私はそれが何を意味するか分かりません!私がしたら、私の問題は解決するかもしれないと思う。 –

+1

あなたはその記事を読んでいますか? – sharptooth

+0

はい私は今あります。それは関連しているように見えますが、何を変えるべきか私には何の考えも与えません。サーバーアプリケーションは何年も稼働しており、新しいクライアントMFCアプリケーションを使用して対話しました。私はその記事で「マーシャルを抑制する」方法について何の言及も見ていません。 –

0

以前のコメントが返され、 は、しかし、私たちの答え/修正のための はSTA(シングルスレッドアパートメント)であることをメインアプリケーション(CoCreateInstanceを呼び出す1)を強制することでした、これはすなわち、高度なリンカオプションを設定することにより行った:

「CLRスレッド属性は、」あなたは

またはリンクコマンドラインで「STA属性をスレッド」に設定されていますdo:

"/CLRTHREADATTRIBUTE:STA" 

これにより、MTAとSTAが混在してスレッド間で呼び出しが行われなくなります。

他の人がこの情報を役立ててくれることを願っています。

関連する問題