Fange events fra en .NET COM server i en C++ klient
Hej.Jeg vil gerne fange events fra en .NET COM server som er skrevet i C#, i en unmanaged C++ applikation.
Jeg har compilet C# serveren og reistreret den med regasm /tlb csserver.dll
og installeret den i GAC med gacutil -i csserver.dll
C++ klienten compiler også uden fejl men fanger ikke eventen.
Er der nogen der kan se hvad jeg gør galt ?
//----------------------------------------------------------------
using System;
using System.Collections;
using System.Threading;
using System.Runtime.InteropServices;
namespace TheNamespace {
[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("TheNamespace.SomeClass")]
[Guid("CFEA397B-41AD-4dc4-8F5B-95E1ED0B5A62")]
public class SomeClass {
private int someVar;
public SomeClass() {}
public SomeClass( int i ) {
this.SomeVar = i;
}
public int foo() {
return 42;
}
public int SomeVar {
get { return someVar; }
set { this.someVar = value; }
}
public void Show() {
Console.WriteLine( "Value is:" + this.SomeVar );
}
}
[ComSourceInterfaces(typeof(_DEventInterface))]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("TheNamespace.SomeClassCollection")]
[Guid("B84B24B7-5184-4256-A4B3-6172DB78E8CB")]
public class SomeClassCollection : IEnumerable {
private ArrayList theCollection = new ArrayList();
[ComVisible(false)]
public delegate void NotifyCallback();
public event NotifyCallback NotifyEvent;
public SomeClassCollection() {
theCollection.Add( new SomeClass( 3 ));
theCollection.Add( new SomeClass( 5 ));
theCollection.Add( new SomeClass( 7 ));
theCollection.Add( new SomeClass( 9 ));
}
public IEnumerator GetEnumerator() {
return theCollection.GetEnumerator();
}
public void TriggerEvent() {
NotifyEvent();
}
public void Add( SomeClass o ) {
theCollection.Add( o );
this.Notify();
}
public void RemoveAt( int i ) {
theCollection.RemoveAt( i );
// this.Notify();
}
public void Clear() {
theCollection.Clear();
// this.Notify();
}
private void Notify() {
// NotifyEvent( "event" );
}
}
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[Guid("A604AB66-E064-4363-8B2B-8433001C47E5")]
public interface _DEventInterface {
[DispId(1)] void NotifyEvent();
}
}
/*[ClassInterface(ClassInterfaceType.AutoDual)]
public class SomeService {}*/
//----------------------------------------------------------------
#import "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\mscorlib.tlb" no_namespace named_guids rename( "_Module", "_NETModule" )
#import "C:\Documents and Settings\CodeCow\Desktop\Interop\CsServer\bin\Debug\CsServer.tlb" no_namespace named_guids
#include <atlbase.h>
CComModule _Module;
#include <atlcom.h>
#include <windows.h>
#include <iostream>
#include <tchar.h>
using namespace std;
_ATL_FUNC_INFO NotifyEventInfo =
{ CC_STDCALL, VT_EMPTY, 0, {VT_BSTR}};
class SomeClassCollectionEventSink :
public IDispEventSimpleImpl
< 1, SomeClassCollectionEventSink, &DIID__DEventInterface >
{
public:
BEGIN_SINK_MAP( SomeClassCollectionEventSink )
SINK_ENTRY_INFO( 1, DIID__DEventInterface, 1, NotifyEvent, &NotifyEventInfo )
END_SINK_MAP()
void __stdcall NotifyEvent( BSTR msg ) {
USES_CONVERSION;
cout << "got event" << endl;
SysFreeString( msg );
}
SomeClassCollectionEventSink( _SomeClassCollection* pObj ) {
pDotNetObject = pObj;
pDotNetObject -> AddRef();
DispEventAdvise((IUnknown*) pDotNetObject );
}
~SomeClassCollectionEventSink() {
pDotNetObject -> Release();
DispEventUnadvise((IUnknown*) pDotNetObject );
}
private:
_SomeClassCollection* pDotNetObject;
};
int main( int argc, char* argv[] ) {
USES_CONVERSION;
HRESULT hres;
hres = CoInitialize( NULL );
if( hres != S_OK ) {
return -1;
}
try {
// Set event sinken op
_SomeClassCollection *pEvent = NULL;
CoCreateInstance( CLSID_SomeClassCollection, NULL, CLSCTX_SERVER,
IID__SomeClassCollection, (void**) &pEvent );
SomeClassCollectionEventSink theSink((_SomeClassCollection*) pEvent );
// benyt collectionen
_SomeClassCollectionPtr colPtr(
__uuidof(SomeClassCollection));
IEnumVARIANTPtr enumPtr =
colPtr -> GetEnumerator();
VARIANT theSomeClasses[10];
ULONG numReturned = 0;
enumPtr -> Next( 5, theSomeClasses, &numReturned );
cout << "Read: " << numReturned << endl;
_SomeClassPtr objPtr;//( __uuidof(SomeClass));
for( int i=0; i<numReturned; i++ ) {
objPtr = theSomeClasses[i].punkVal;
objPtr -> Show();
}
objPtr -> PutSomeVar( 6 );
objPtr -> Show();
cout << "About to add" << endl;
colPtr->Add( objPtr );
cout << "About to trigger event" << endl;
colPtr->TriggerEvent();
colPtr->Release();
} catch(_com_error &e) {
endl << "caught error"<< endl;
}
CoUninitialize();
return 0;
}