実行時バインディングで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' のイベントではありません。
コンパイルエラーってことは
独自イベントだと参照設定あたりはしないと駄目なのかもね。
Private TargetObj As Test.SampleCOM
(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
返事が遅くなりまして,申し訳ありません.
魔界の仮面弁士さんの方法で作成してみましたが,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
>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
:
:
失礼しました。
ComVisible属性を付加する場所を間違いました。
(訂正)
<System.Runtime.InteropServices.ComVisible(True)> _
Public Class MyEventSink
Implements IMyEvent
Public Sub OnChangeItem() Implements IMyEvent.TestEvent
MsgBox("OnChangeItem")
End Sub
End Class
Abyssさん,回答ありがとうございます.
クラスのプロパティを確認しましたが,「COM参照」はデフォルトでTRUEになっていました.
明示的にComVisible属性をTrueにもしてみましたが,結果は変わらず
「0x80040202」のエラーが発生します.
一般的な例を提示したいと思います。
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
> 「0x80040202」のエラーが発生します.
CONNECT_E_CANNOTCONNECT かな。
http://support.microsoft.com/kb/183216/ja
ツイート | ![]() |