実行時バインディングでCOMサーバのイベントをとる方法


ひっしー  2008-05-24 06:04:05  No: 144778

実行時バインディングでCOMサーバのイベントを取得したいのですが
うまくいきません.
どのようにしたら取得できるのでしょうか.

開発環境:VB2005

ソース:

Public Class Form1

    Private TargetObj As Object

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        ' オブジェクトの生成
        TargetObj = CreateObject("Test.SampleCOM")

        'イベントハンドラの作成
        AddHandler TargetObj.TestEvent, AddressOf TargetObj_TestEvent

    End Sub

    Private Sub TargetObj_TestEvent()
        MsgBox("OK")
    End Sub

End Class

コンパイル結果:
Form1.vb(12) : error BC30676: 'TestEvent' は 'Object' のイベントではありません。


やじゅ  2008-05-24 06:21:10  No: 144779

コンパイルエラーってことは
独自イベントだと参照設定あたりはしないと駄目なのかもね。
Private TargetObj As Test.SampleCOM


魔界の仮面弁士  2008-05-24 06:50:47  No: 144780

(1) COM オブジェクトを、System.Runtime.InteropServices.ComTypes.IConnectionPointContainer
  インターフェイスにキャストする。

(2) IConnectionPointContainer の FindConnectionPoint メソッドに、
  自分が持っている通知インタフェースのIID(または DIID)を指定して、
  IConnectionPoint インターフェイスを得る。

(3) そこで得た IConnectionPoint に対し、Advise メソッドにて
  自分が持っている通知インタフェースを登録してやれば準備完了。
  (登録解除は Unadvise メソッド)

下記は、旧形式(UCOMIConnectionPointContainer)を使ったサンプルですが、
IConnectionPointContainer でも、処理の流れは同様です。
http://support.microsoft.com/kb/810228/ja


ひっしー  2008-05-27 20:14:25  No: 144781

返事が遅くなりまして,申し訳ありません.

魔界の仮面弁士さんの方法で作成してみましたが,Adviseの箇所で失敗します.
やはり参照設定をしてイベントインターフェースを取得しなければ行けないのでしょうか.

ソース:

===== MyEventSink.vb ==============
Public Interface IMyEvent
    Sub TestEvent()
End Interface

Public Class MyEventSink
    Implements IMyEvent

    Public Sub OnChangeItem() Implements IMyEvent.TestEvent
        MsgBox("OnChangeItem")
    End Sub
End Class

===== Form1.vb ==============
Imports System
Imports System.Runtime.InteropServices.ComTypes

Public Class Form1
    Private TestObj As Object

    Private icp As IConnectionPoint
    Private cookie As Integer
    Private mySink As MyEventSink

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        ' オブジェクトの生成
        TestObj = CreateObject("TestSrv.Test1")

        ' イベントシンクの作成
        mySink = New MyEventSink

        ' コネクションポイントインターフェースの取得
        Dim icpc As IConnectionPointContainer = CType(TestObj, IConnectionPointContainer)

        ' 通知インターフェースのDIID
        Dim EventIID As New Guid("1A04232B-1F21-43AF-89FB-31C5B5FDE49C")
        icpc.FindConnectionPoint(EventIID, icp)

        ' アドバイスループの確立
        icp.Advise(mySink, cookie)
    End Sub

    Private Sub Form1_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
        ' アドバイスループの切断
        icp.Unadvise(cookie)
    End Sub
End Class


Abyss  2008-05-28 03:36:30  No: 144782

>Adviseの箇所で失敗します.

ClassのComVisible属性をTrueにする必要があると思います。

<System.Runtime.InteropServices.ComVisible(True)> _
Public Class Form1
    Private TestObj As Object

    Private icp As IConnectionPoint
    Private cookie As Integer
    Private mySink As MyEventSink
        :
        :


Abyss  2008-05-28 03:50:05  No: 144783

失礼しました。
ComVisible属性を付加する場所を間違いました。

(訂正)

<System.Runtime.InteropServices.ComVisible(True)> _
Public Class MyEventSink
    Implements IMyEvent

    Public Sub OnChangeItem() Implements IMyEvent.TestEvent
        MsgBox("OnChangeItem")
    End Sub
End Class


ひっしー  2008-05-28 19:58:22  No: 144784

Abyssさん,回答ありがとうございます.

クラスのプロパティを確認しましたが,「COM参照」はデフォルトでTRUEになっていました.
明示的にComVisible属性をTrueにもしてみましたが,結果は変わらず
「0x80040202」のエラーが発生します.


Abyss  2008-05-28 22:29:28  No: 144785

一般的な例を提示したいと思います。
Excelのイベントの例です。

Option Strict Off

Imports System.Reflection
Imports System.Runtime.InteropServices
Imports System.Runtime.InteropServices.ComTypes

<ComVisible(True)> _
Public Class Form1

    Dim mCookie As Integer
    Dim p As IConnectionPoint
    Dim XL As Object

    Private Sub Form1_Load(ByVal sender As Object, _
                ByVal e As EventArgs) Handles MyBase.Load
        AddHandler Button1.Click, AddressOf BtnOnClick
    End Sub

    Private Sub BtnOnClick(ByVal o As Object, ByVal e As EventArgs)
        XL = CreateObject("Excel.Application")
        XL.Visible = True
        Dim c As IConnectionPointContainer = _
                DirectCast(XL, IConnectionPointContainer)

        'Excel AppEventのuuid ...
        Dim guid As New Guid("00024413-0000-0000-C000-000000000046")

        c.FindConnectionPoint(guid, p)
        p.Advise(Me, mCookie)

    End Sub

    ' 例えとしてのイベント ...
    ' Excelで新規bookが作られたら発生します。

    <DispId(&H61D)> _
    Public Sub NewWorkbook(ByVal Wb As Object)
        'Excel各Objectの後始末処理は省略 ...
        Wb.Sheets(1).Cells(1).Value2 = Wb.Name
    End Sub

End Class


魔界の仮面弁士  2008-05-29 03:08:29  No: 144786

> 「0x80040202」のエラーが発生します.
CONNECT_E_CANNOTCONNECT かな。
http://support.microsoft.com/kb/183216/ja


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加