Hilfestellung?? Arbeiten mit COM-Interfaces ?



  • Hallo,

    hatte einen vorherigen Beitrag bereits geschrieben.

    Ich habe eine IDL-Datei die mir eine bzw. mehrere verschiedene Schnittstellen zu einem OPC-Server anbietet.

    Im Handling mit diesen Schnittstellen habe ich nun aber meine Probleme:
    Es gelingt mir einfach nicht, auf diese COM-Schnittstelle zu zugreifen.

    Die Schnittstelle selbst ist von der OPC-Foundation in der Schnittstellendatei bzw. das daraus generierte Headerfile so definiert:

    #ifndef __IOPCBrowseServerAddressSpace_INTERFACE_DEFINED__
    #define __IOPCBrowseServerAddressSpace_INTERFACE_DEFINED__
    
    /* interface IOPCBrowseServerAddressSpace */
    /* [unique][uuid][object] */ 
    
    EXTERN_C const IID IID_IOPCBrowseServerAddressSpace;
    
    #if defined(__cplusplus) && !defined(CINTERFACE)
    
        MIDL_INTERFACE("39c13a4f-011e-11d0-9675-0020afd8adb3")
        IOPCBrowseServerAddressSpace : public IUnknown
        {
        public:
            virtual HRESULT STDMETHODCALLTYPE QueryOrganization( 
                /* [out] */ OPCNAMESPACETYPE __RPC_FAR *pNameSpaceType) = 0;
    
            virtual HRESULT STDMETHODCALLTYPE ChangeBrowsePosition( 
                /* [in] */ OPCBROWSEDIRECTION dwBrowseDirection,
                /* [string][in] */ LPCWSTR szString) = 0;
    
            virtual HRESULT STDMETHODCALLTYPE BrowseOPCItemIDs( 
                /* [in] */ OPCBROWSETYPE dwBrowseFilterType,
                /* [string][in] */ LPCWSTR szFilterCriteria,
                /* [in] */ VARTYPE vtDataTypeFilter,
                /* [in] */ DWORD dwAccessRightsFilter,
                /* [out] */ LPENUMSTRING __RPC_FAR *ppIEnumString) = 0;
    
            virtual HRESULT STDMETHODCALLTYPE GetItemID( 
                /* [in] */ LPWSTR szItemDataID,
                /* [string][out] */ LPWSTR __RPC_FAR *szItemID) = 0;
    
            virtual HRESULT STDMETHODCALLTYPE BrowseAccessPaths( 
                /* [string][in] */ LPCWSTR szItemID,
                /* [out] */ LPENUMSTRING __RPC_FAR *ppIEnumString) = 0;
    
        };
    
    #else 	/* C style interface */
    
        typedef struct IOPCBrowseServerAddressSpaceVtbl
        {
            BEGIN_INTERFACE
    
            HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( 
                IOPCBrowseServerAddressSpace __RPC_FAR * This,
                /* [in] */ REFIID riid,
                /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
    
            ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( 
                IOPCBrowseServerAddressSpace __RPC_FAR * This);
    
            ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( 
                IOPCBrowseServerAddressSpace __RPC_FAR * This);
    
            HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryOrganization )( 
                IOPCBrowseServerAddressSpace __RPC_FAR * This,
                /* [out] */ OPCNAMESPACETYPE __RPC_FAR *pNameSpaceType);
    
            HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ChangeBrowsePosition )( 
                IOPCBrowseServerAddressSpace __RPC_FAR * This,
                /* [in] */ OPCBROWSEDIRECTION dwBrowseDirection,
                /* [string][in] */ LPCWSTR szString);
    
            HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BrowseOPCItemIDs )( 
                IOPCBrowseServerAddressSpace __RPC_FAR * This,
                /* [in] */ OPCBROWSETYPE dwBrowseFilterType,
                /* [string][in] */ LPCWSTR szFilterCriteria,
                /* [in] */ VARTYPE vtDataTypeFilter,
                /* [in] */ DWORD dwAccessRightsFilter,
                /* [out] */ LPENUMSTRING __RPC_FAR *ppIEnumString);
    
            HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetItemID )( 
                IOPCBrowseServerAddressSpace __RPC_FAR * This,
                /* [in] */ LPWSTR szItemDataID,
                /* [string][out] */ LPWSTR __RPC_FAR *szItemID);
    
            HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BrowseAccessPaths )( 
                IOPCBrowseServerAddressSpace __RPC_FAR * This,
                /* [string][in] */ LPCWSTR szItemID,
                /* [out] */ LPENUMSTRING __RPC_FAR *ppIEnumString);
    
            END_INTERFACE
        } IOPCBrowseServerAddressSpaceVtbl;
    
        interface IOPCBrowseServerAddressSpace
        {
            CONST_VTBL struct IOPCBrowseServerAddressSpaceVtbl __RPC_FAR *lpVtbl;
        };
    
    #ifdef COBJMACROS
    
    #define IOPCBrowseServerAddressSpace_QueryInterface(This,riid,ppvObject)	\
        (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
    
    #define IOPCBrowseServerAddressSpace_AddRef(This)	\
        (This)->lpVtbl -> AddRef(This)
    
    #define IOPCBrowseServerAddressSpace_Release(This)	\
        (This)->lpVtbl -> Release(This)
    
    #define IOPCBrowseServerAddressSpace_QueryOrganization(This,pNameSpaceType)	\
        (This)->lpVtbl -> QueryOrganization(This,pNameSpaceType)
    
    #define IOPCBrowseServerAddressSpace_ChangeBrowsePosition(This,dwBrowseDirection,szString)	\
        (This)->lpVtbl -> ChangeBrowsePosition(This,dwBrowseDirection,szString)
    
    #define IOPCBrowseServerAddressSpace_BrowseOPCItemIDs(This,dwBrowseFilterType,szFilterCriteria,vtDataTypeFilter,dwAccessRightsFilter,ppIEnumString)	\
        (This)->lpVtbl -> BrowseOPCItemIDs(This,dwBrowseFilterType,szFilterCriteria,vtDataTypeFilter,dwAccessRightsFilter,ppIEnumString)
    
    #define IOPCBrowseServerAddressSpace_GetItemID(This,szItemDataID,szItemID)	\
        (This)->lpVtbl -> GetItemID(This,szItemDataID,szItemID)
    
    #define IOPCBrowseServerAddressSpace_BrowseAccessPaths(This,szItemID,ppIEnumString)	\
        (This)->lpVtbl -> BrowseAccessPaths(This,szItemID,ppIEnumString)
    
    #endif /* COBJMACROS */
    
    #endif 	/* C style interface */
    
    HRESULT STDMETHODCALLTYPE IOPCBrowseServerAddressSpace_QueryOrganization_Proxy( 
        IOPCBrowseServerAddressSpace __RPC_FAR * This,
        /* [out] */ OPCNAMESPACETYPE __RPC_FAR *pNameSpaceType);
    
    void __RPC_STUB IOPCBrowseServerAddressSpace_QueryOrganization_Stub(
        IRpcStubBuffer *This,
        IRpcChannelBuffer *_pRpcChannelBuffer,
        PRPC_MESSAGE _pRpcMessage,
        DWORD *_pdwStubPhase);
    
    HRESULT STDMETHODCALLTYPE IOPCBrowseServerAddressSpace_ChangeBrowsePosition_Proxy( 
        IOPCBrowseServerAddressSpace __RPC_FAR * This,
        /* [in] */ OPCBROWSEDIRECTION dwBrowseDirection,
        /* [string][in] */ LPCWSTR szString);
    
    void __RPC_STUB IOPCBrowseServerAddressSpace_ChangeBrowsePosition_Stub(
        IRpcStubBuffer *This,
        IRpcChannelBuffer *_pRpcChannelBuffer,
        PRPC_MESSAGE _pRpcMessage,
        DWORD *_pdwStubPhase);
    
    HRESULT STDMETHODCALLTYPE IOPCBrowseServerAddressSpace_BrowseOPCItemIDs_Proxy( 
        IOPCBrowseServerAddressSpace __RPC_FAR * This,
        /* [in] */ OPCBROWSETYPE dwBrowseFilterType,
        /* [string][in] */ LPCWSTR szFilterCriteria,
        /* [in] */ VARTYPE vtDataTypeFilter,
        /* [in] */ DWORD dwAccessRightsFilter,
        /* [out] */ LPENUMSTRING __RPC_FAR *ppIEnumString);
    
    void __RPC_STUB IOPCBrowseServerAddressSpace_BrowseOPCItemIDs_Stub(
        IRpcStubBuffer *This,
        IRpcChannelBuffer *_pRpcChannelBuffer,
        PRPC_MESSAGE _pRpcMessage,
        DWORD *_pdwStubPhase);
    
    HRESULT STDMETHODCALLTYPE IOPCBrowseServerAddressSpace_GetItemID_Proxy( 
        IOPCBrowseServerAddressSpace __RPC_FAR * This,
        /* [in] */ LPWSTR szItemDataID,
        /* [string][out] */ LPWSTR __RPC_FAR *szItemID);
    
    void __RPC_STUB IOPCBrowseServerAddressSpace_GetItemID_Stub(
        IRpcStubBuffer *This,
        IRpcChannelBuffer *_pRpcChannelBuffer,
        PRPC_MESSAGE _pRpcMessage,
        DWORD *_pdwStubPhase);
    
    HRESULT STDMETHODCALLTYPE IOPCBrowseServerAddressSpace_BrowseAccessPaths_Proxy( 
        IOPCBrowseServerAddressSpace __RPC_FAR * This,
        /* [string][in] */ LPCWSTR szItemID,
        /* [out] */ LPENUMSTRING __RPC_FAR *ppIEnumString);
    
    void __RPC_STUB IOPCBrowseServerAddressSpace_BrowseAccessPaths_Stub(
        IRpcStubBuffer *This,
        IRpcChannelBuffer *_pRpcChannelBuffer,
        PRPC_MESSAGE _pRpcMessage,
        DWORD *_pdwStubPhase);
    
    #endif 	/* __IOPCBrowseServerAddressSpace_INTERFACE_DEFINED__ */
    

    Darauf hin habe ich in meiner Client-Anwendung eine Methode geschrieben, die mir eben eine Instanz der Schnittstelle zurück liefern soll:

    IOPCBrowseServerAddressSpace* InstantiateOPCBrowseServerAddressSpace(wchar_t ServerName[])
    {
    	HRESULT hr;
    	CLSID CLSID_OPCServer; 
    	CLSID CLSID_OPCServer2;
    
    	void** ppIntfObj = NULL;
    
    	// Get GUID and UUID from regsitry for COM-Server
    	hr = CLSIDFromProgID(ServerName, &CLSID_OPCServer2);
    	ShowError(hr);
    
    	// Queue of Class-Instances to create
    	LONG cmq = 1; // number of class instances to create
    	MULTI_QI queue[1] = {{&IID_IOPCBrowseServerAddressSpace,
    						  NULL,
    						  0}};
    
    	//Create an instance of the IOPCBrowse
    	hr = CoCreateInstanceEx(CLSID_OPCServer, NULL, CLSCTX_SERVER, /*&CoServerInfo */ NULL,
    							cmq, queue);
    	ShowError(hr);
    
    	// Return Pointer to the IOPCBrowse Interface
    	return(IOPCBrowseServerAddressSpace*) queue[0].pItf;
    }
    

    Diese Methode liefert mir auch einen entsprechenden Poiner auf eine Adresse zurück. Bis hierhin treten auch keine Fehlercodes auf!

    Dann rufe ich dies in meiner Main-Funktion folgender Maßen auf:

    CoInitialize(NULL); //Using MS Com library
    
    	//Instanciate Browse-Interface
    	IOPCBrowseServerAddressSpace *pOPCBrowse2 = InstantiateOPCBrowseServerAddressSpace(L"SOFTING.OPCToolboxDemo_ServerDA");
    	//Declarations for OPCBrowse
    	HRESULT hr;
    
    	OPCBROWSEDIRECTION dwBrowseDir = OPC_BROWSE_TO;
    
    	hr = pOPCBrowse2->ChangeBrowsePosition(dwBrowseDir, NULL);
    	ShowError(hr);
    
    	OPCNAMESPACETYPE *pNameSpaceType;
    	hr = pOPCBrowse2->QueryOrganization(pNameSpaceType);
    	ShowError(hr);
    
    	OPCBROWSETYPE dwBrowseType = OPC_FLAT;
    	LPENUMSTRING *pIEnumString;
    
    	hr = pOPCBrowse2->BrowseOPCItemIDs(dwBrowseType, NULL /*Filter*/, 0, 0, pIEnumString);
    	ShowError(hr);
    
    	...
    

    Hier tritt entweder ein unbekannter Fehlertyp auf (beim ersten Aufrruf ChangeBrowsePosition, Fehlercode 0x000006F4 (Kernel32.dll)
    Oder eben eine Access Violation (0xC0000005, in RPCRT4.dll)-Fehlertyp auf!

    Mache ich hier bezüglich der COM-Aufrufe was falsch ? Ich habe auch versucht über QueryInterface ranzukommen, dort kommt er jedoch mit Invalid Arguments-Fehler zurück, ich denke mal im Zusammenhang der IID oder CLSID des COM-Servers.

    Vielleicht hat jemand von euch dort eine Idee ?

    Würde mir echt weiterhelfen.
    Vielen Dank schonmal...

    Biasto


  • Mod

    Biasto schrieb:

    // Queue of Class-Instances to create
    	LONG cmq = 1; // number of class instances to create
    	MULTI_QI queue[1] = {{&IID_IOPCBrowseServerAddressSpace,
    						  NULL,
    						  0}};
    
    	//Create an instance of the IOPCBrowse
    	hr = CoCreateInstanceEx(CLSID_OPCServer, NULL, CLSCTX_SERVER, /*&CoServerInfo */ NULL,
    							cmq, queue);
    	ShowError(hr);
    

    Und was sagt hr? Ist es S_OK?
    Ist vor allem queue[0].hr==S_OK! Ansonsten ist der Interfacezeiger ungültig!

    Wenn Du nur ein einziges Interface abfragst. Warum nutzt Du nicht CoCreateInstance?



  • hr ist an dieser Stelle 0.

    Hab ja auch gesagt, dass er einen validen Zeiger zurückgibt.

    Jedoch gelingt mir dies mit CoCreateInstance nicht, ein positives Ergtebnis zu erlangen, dort bekomme ich immer den Fehlercode Invalid Arguments zurück.

    Ist auch eine Sache, die mich gewundert hat!

    Das Problem ist mehr, das der Zeiger nicht auf das richtige Interface zeigt, oder ich Zugriffsprobleme darauf habe?


  • Mod

    Nochmal: Bei hr in der Struktur und der Rückgabewert sind beide S_OK?



  • Was heisst bei hr in der Struktur ?

    Der Rückgabewert von CoCreateInstanceEx ist 0, und ich glaube das bedeutet S_OK.

    Es treten erst unbekannte Fehler auf, wenn ich versuche mit dem übergebenen Pointer auf das Interface zu zugreifen...


  • Mod

    Du hast es nicht verstanden! Doku lesen zu CoCreateInstanceEx!

    MULTI_QI hat einen member hr, dieser gibt Auskunft ob der Zeiger in diesem Slot valide ist!
    Also ist nun queue[0].hr==S_OK?



  • Woher nehmen und nicht stehlen...

    der hr-Code in der STruktur ist null, sowie der Rückgabewert der Funktion CoCreateInstanceEx.

    Beim Aufruf des Interfaces:

    hr = pOPCBrowse->ChangeBrowsePosition(dwBrowseDir, NULL);
    

    gibt er mir den Fehler "An den Stub wurde ein Nullzeiger übergeben" zurück!

    bei den anderen beiden Aufrufen:

    hr = pOPCBrowse->QueryOrganization(pNameSpaceType);
    //und
    hr = pOPCBrowse->BrowseOPCItemIDs(dwBrowseType, NULL, 0, 0, pIEnumString);
    

    bekomme ich den fehlercode für "Zugriff verweigert" zurück.

    Ich hoffe meine Informationen sind nun etwas genauer


  • Mod

    Befindet sich das Objekt auf Deinem Rechner, oder ist das ein DCOM Zugriff?

    Ansonsten wende Dich vertrauensvoll an den Support desjenigen der dieses COM Objekt erzeugt hat!



  • Ja, das Objekt ist lokal auf dem Rechner!

    Naja... die Alternative bietet sich leider nicht 😞
    So'n Dreck da!



  • Öh, du verwendest doch da den Demo Server von Softing.

    Warum benutzt du dann nicht das zugehörige Toolkit um darauf zuzugreifen ?



  • Der Demo-Server dient mir nur als OPC Server, der ein wenig Space hat!

    Wir haben Softings Produkte nicht lizenziert, sondern hatten vor x Jahren mal ein Toolkit von TSOPC gekauft (TechnoSoftware), damals war aber die browse-Funktion noch nicht bei TsOPC implementiert, die wir nun auf Kundenwunsch benötigen.

    Da ein Upgrade jedoch inkompatibel zu unserem bestehenden Projekt ist, zu dem kostenpflichtig ist, war die erste Idee, eben diesen OPC-Interface-Zugriff selbst zu programmieren!



  • Ich stehe gerade auch vor dem Problem OPC Zugriff in ein Programm einzubauen, das bisher keinen hat.

    Ein kurzer Blick auf die OPC COM Interfaces und ein paar Tests mit der Demo Version des Toolkits machten uns schnell klar, das kaufen hier billiger ist als selber schreiben.


Anmelden zum Antworten