Reputation: 1205
I have a COM object with the main interface and the events interface (from the IDL file):
[
uuid(<interfaceId>,
helpstring("AxBitViewerWidget Interface")
]
dispinterface IAxBitViewerWidget
{
...
};
[
uuid(<eventsId>),
helpstring("AxBitViewerWidget Events Interface")
]
dispinterface IAxBitViewerWidgetEvents
{
...
};
[
aggregatable,
helpstring("AxBitViewerWidget Class"),
uuid(<mainClassId>),
control
]
coclass AxBitViewerWidget
{
[default] dispinterface IAxBitViewerWidget;
[default, source] dispinterface IAxBitViewerWidgetEvents;
};
It was automatically created by Active Qt.
Then in C# (in another dll) I want to connect to this COM object and handle its events.
The C# class is inherited from AxHost
. All COM types are dynamic in my example and used via Reflection. Here is the snippet:
public class BitViewerEx : AxHost
{
public BitViewerEx()
: base(<mainClassId>)
{
}
private void Initialize()
{
try
{
object ocx = GetOcx();
if (ocx != null)
{
Type ocxType = ocx.GetType();
Guid eventsGuid = new Guid(<eventsId>);
Type eventsType = Type.GetTypeFromCLSID(eventsGuid);
var sinkEventsInterfaceObj = CreateInstanceCore(eventsGuid);
// runtime error here
var cookie = new ConnectionPointCookie(ocx, sinkEventsInterfaceObj, eventsType);
}
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.ToString());
}
}
}
When calling ConnectionPointCookie from the above - an error occurs (approximately translated from localized message): "Cannot execute Advise() for the event interface '__ComObject'".
Is my code correct? How to correctly connect AxBase to the COM object events? (for dynamic types case, cannot use IAxBitViewerWidgetEvents etc. in C# code)
P.S.: class methods (not events) are called without an issue, like:
ocx.GetType().InvokeMember("initialize", System.Reflection.BindingFlags.InvokeMethod,
null, ocx, new object[] { this.argum1, this.argum2 });
P.S.2: The following code returns an empty array:
System.Reflection.EventInfo[] arr = ocx.GetType().GetEvents();
Upvotes: 0
Views: 287
Reputation: 1205
Finally I got it working. The main class is inherited like this
public class BitViewerEx : AxHost, IBitViewerEvents
where IBitViewerEvents
is (based on the contents of the corresponding auto-generated .idl file)
// Methods should be like signals in the Qt active-x class with the bit viewer.
// DispIds are taken from the .idl file for the corresponding methods.
[ComImport, Guid(<eventsId>)]
public interface IBitViewerEvents
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(8)]
void started();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(9)]
void stopped();
}
Then the connection code for all events is simplified to:
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
...
private void Initialize() // BitViewerEx class member
{
try
{
object ocx = GetOcx();
if (ocx != null)
{
ocx.GetType().InvokeMember("initialize", System.Reflection.BindingFlags.InvokeMethod,
null, ocx, new object[] { this.deviceAddress, this.cellAddress });
var cookie = new ConnectionPointCookie(ocx, this, typeof(IBitViewerEvents));
}
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.ToString());
}
}
Upvotes: 0