Avatar billede codecow Nybegynder
12. juni 2005 - 16:57 Der er 4 kommentarer og
1 løsning

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;
}
Avatar billede codecow Nybegynder
12. juni 2005 - 17:03 #1
Outputtet er:

Read: 4
Value is:3
Value is:5
Value is:7
Value is:9
Value is:6
About to add
About to trigger event
caught error
Avatar billede codecow Nybegynder
12. juni 2005 - 17:17 #2
Jeg har lige opdaget at i den ovenstående version sender jeg ikke en event afsted med en string, hvilket jeg har rettet og reregistreret komponenten, men fejlen er den samme :(
Avatar billede cplus Nybegynder
13. juni 2005 - 16:04 #3
Nu vil jeg så absolut ikk påstå jeg er en COM guru. Er mindst 2 år siden jeg har brugt det.

Men er C# events ikke asynkrone? Når de frem?

Desuden ser det ikk ud til at dit NotifyEvent er tidelt nogen event handler.. I C# er en event jo blot en (virtuel pointer) pointer til en metode. Så du har godt nok defineret et delegate / event pattern, men evented er NULL og derfor invokes din metode pointer aldrig. Det er min spådom
Avatar billede codecow Nybegynder
14. juni 2005 - 18:30 #4
ok... det var vist en fejl 40 :)

hvis jeg skifter

_SomeClassCollectionPtr colPtr(
    __uuidof(SomeClassCollection));

ud med

_SomeClassCollectionPtr colPtr = pEvent;

Så virker alting ;)

Mange tak for hjælpen. Hvis du vil have point så smid et svar.
Avatar billede cplus Nybegynder
17. juni 2005 - 09:02 #5
svar.. :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester