2012-02-14 8 views
2

DispIDを使用して別の.NETアプリケーションから.NETで定義されたCOMオブジェクトのメソッドを呼び出すとします。.NETで.NETで定義されたCOMオブジェクトの遅延バインディング呼び出し(DispID経由)を実行する方法は?

私は、.NETプロジェクトで定義された以下のクラスとインターフェイスを持っている:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Runtime.InteropServices; 

namespace TestComObject 
{ 
    [ComVisible(true)] 
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 
    [Guid("99476c04-574a-4271-abc8-f1d2615c3d93")] 
    public interface IKnowEverything 
    { 
     [DispId(1030)] 
     string GetTheTruth(); 
    } 

    [ComVisible(true)] 
    [Guid("9B869BAF-622A-458B-BF80-2CD6D8A3C541")] 
    [ClassInterface(ClassInterfaceType.None)] 
    public class AllKnowing : IKnowEverything 
    { 
     public string GetTheTruth() 
     { 
     return "I am King!"; 
     } 
    } 
} 

私はそれを構築し、それはCOM相互運用機能に登録するように設定されている、それは強力な鍵で署名されています。

今、別の.NETアプリケーションのDispIDを使用してこのメ​​ソッドを呼び出す必要があります。私は次のテスト方法を書いた:

最初の呼び出しは成功し、 "Via name:I am King!"と印刷されます。

しかし、(DISPIDを使用して)2番目の呼び出しに私は例外を取得:

未処理の例外を:System.MissingMethodException:メソッド 'TestComObject.AllKnowing [DISPID = 1030]。' が見つかりません。

OLE-COMオブジェクトビューアでそれを見たときに、タイプライブラリは私に大丈夫になります

// Generated .IDL file (by the OLE/COM Object Viewer) 
// 
// typelib filename: TestComObject.tlb 

[ 
    uuid(139DAA99-BF76-4057-BCC8-DCB35C153920), 
    version(1.0), 
    custom(90883F05-3D28-11D2-8F17-00A0C9A6186D, "TestComObject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=58b6bd22fbd98427") 

] 
library TestComObject 
{ 
    // TLib :  // TLib : mscorlib.dll : {BED7F4EA-1A96-11D2-8F08-00A0C9A6186D} 
    importlib("mscorlib.tlb"); 
    // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046} 
    importlib("stdole2.tlb"); 

    // Forward declare all types defined in this typelib 
    dispinterface IKnowEverything; 

    [ 
     uuid(99476C04-574A-4271-ABC8-F1D2615C3D93), 
     version(1.0), 
     custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "TestComObject.IKnowEverything")  

    ] 
    dispinterface IKnowEverything { 
     properties: 
     methods: 
      [id(0x00000406)] 
      BSTR GetTheTruth(); 
    }; 

    [ 
     uuid(9B869BAF-622A-458B-BF80-2CD6D8A3C541), 
     version(1.0), 
     custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "TestComObject.AllKnowing") 
    ] 
    coclass AllKnowing { 
     interface _Object; 
     [default] dispinterface IKnowEverything; 
    }; 
}; 

は、私がここで間違って何をしているのですか?

+0

ハンス・パッサントの回答:http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/0cc7543e-2678-4e0f-84c8-bc2ad56e09e5/「[DispID = 1030] "メンバの名前として、' Type.GetTypeFromCLSID'ではなく 'Type.GetTypeFromProgID()'から取り出された型インスタンスに対して 'InvokeMember'を呼び出すべきです – phoog

+0

返される' Type'は、私がそれを取得するかどうかにかかわらず同じでなければなりませんProgIDまたはCLSID、そうではありませんか? – DeCaf

+0

私はそうだと思いますが、GetTypeFromProgIDのドキュメントは、戻り値が常に 'System .__ ComObject'であると思われますが、他のメソッドのドキュメントではこれを説明していません。もちろん、これはフレームワーク文書の不一致やエラーの最初の例ではありません。ハンスはあなたの質問に対して別の答えを出したので、返された 'Type'についてあなたは正しいと思います。 – phoog

答えて

3

.NETでCOMサーバーを実装しているため、これは機能しません。 インスタンスのメンバーは実際の.NETオブジェクトであり、RCWではありません。デバッガから伝えることができるのは、System .__ ComObjectではなく、実際の.NETタイプのオブジェクトです。

したがって、InvokeMember()を使用すると、IDispatchバージョンではなくSystem.Reflectionバージョンが取得されます。それを見る別の方法は "getTheTruth"を使うことです。最初の試行がどのように失敗したかに注目してください。 IDispatchは大文字と小文字を区別しません。System.Reflectionは大文字と小文字を区別しません。 System.Reflectionはdisp-idsについて何も知らないので、「[DispID = 1030]」のトリックは機能しません。

バグではなく、.NETオブジェクトを直接作成できるときにCLRがRCWを作成することは意味がありません。それは簡単に実装することもできません。

+0

情報に感謝しました。それは私が推測するいくつかの点で意味をなさない。 – DeCaf

関連する問題