wie fange ich in C++ Code die Exceptions aus C# COM?



  • audacia schrieb:

    Könntest du mal die Deklaration von OpenWorkspace() in der Headerdatei zeigen?

    Hilft dies aus dem Headerfile der automatisch erzeugte Typelibrary?

    (mit
    typedef LONG HRESULT;)
    HRESULT __fastcall OpenWorkspace(BSTR fileName/[in]/);

    template <class T> HRESULT __fastcall
    IBlablaBlaDispT<T>::OpenWorkspace(BSTR fileName/[in]/)
    {
    _TDispID _dispid(this, OLETEXT("OpenWorkspace"), DISPID(10));
    TAutoArgs<1> _args;
    _args[1] = fileName /
    [VT_BSTR:0]*/;
    return OleFunction(_dispid, _args);
    }



  • Mittlerweile habe ich auch diese zwei Möglichkeiten probiert:

    AnsiString S = SysErrorMessage(xxx->OpenWorkspace(...));
    und alternativ
    xxx->OpenWorkspace(...);
    AnsiString S = SysErrorMessage(GetLastError());

    In beiden Fällen erhalte ich
    "Der Vorgang wurde erfolgreich beendet"

    Bleibt die Frage, was für Vorgang gemeint ist. Das Öffnen von Workspace oder
    dass Borland IDE erfolgreich die Exception bei sich und ohne Beteiligung
    meiner Applikation behandelt hat?



  • audacia schrieb:

    DocShoe schrieb:

    COM? Mit COM Programmiertechniken wird doch alles über Interfaces und Return Codes abgewickelt, da haben Exceptions doch nichts zu suchen ?!

    Wenn es sich um statische Bindung zu einer Typbibliothek handelt, dann sollte für COM-Exceptions zumindest eine EOleException geworfen werden, und wenn er den VCL-Support für Late Binding verwendet, dann eigentlich auch.

    irgendwo im Internet steht, "Late-binding is made possible using a well known COM interface called IDispatch.". Da ich das Wort Dispatch zig mal in com header
    sehe, nehme ich an, hier wird Late Binding unterstützt. (sorry ich habe meine erste Erfahrung mit COM)



  • In der Tat ist das eine Late-binding-Schnittstelle, auch wenn deine Schlußfolgerungen nicht einwandfrei sind 😉 IDispatch zu implementieren heißt lediglich, daß unter anderem eine Late-binding-Schnittstelle zur Verfügung steht. Und in deinem Fall wird sicherlich auch eine Early-Binding-Schnittstelle definiert, die du stattdessen besser benutzt hättest.

    Du kannst die Fehlerbehandlung durch Exceptions auf folgendem Wege aktivieren:
    - Zunächst durch Befolgung der Hinweise in diesem Posting.
    - Dann durch Definieren des Makros __CHECKHR_ON_INVOKE in den Projektoptionen.

    Wenn dann keine Exception geworfen wird, läuft auf der anderen Seite der Schnittstelle etwas schief. Um dir dann besser helfen zu können, wäre es gut, wenn du die komplette COM-Headerdatei zur Verfügung stellen könntest.



  • Hallo aucadia,

    vielen Dank erst mal für die Ratschläge. Ich bin sehr gespannt, wie meine Tests ausfallen. Leider wurde ich bei der Arbeit von dem Thema abgehalten. Ich schreibe meine Ergebnisse sofort hier rein, wenn ich welche habe.

    Viele Grüsse,
    Permana



  • ok, ich habe die Datei zum Projekt addiert und __CHECKHR_ON_INVOKE zu Userdefines addiert. Und in meinem Sourcefile das template DebugHlpr_HRCHECK reingeschrieben.

    Und was passiert? Es heiss immer noch "Der Vorgang wurde erfolgreich abgeschlossen". Und kein Landen im Exceptionzweig.

    Ich werde bei der Arbeit fragen, ob man die COM-Header einfach so rausgeben darf. Ansonsten frage ich unsere Lieferanten, ob sie mit C++ getestet haben.

    Danke und Gruß,
    Permana



  • Hallo allerseits,

    ich kann in den Logfiles meiner COM-Schnittstelle sehen, dass Exception geworfen wird.

    16.07.2010 17:22:29.238 E EXCEPTION GlobalExceptionHandler: Unerwartete Excpeption: System.InvalidCastException: Die angegebene Umwandlung ist ungültig.

    Das bedeutet, dass der C++ Builder, also vermutlich der Debugger diese Exceptions fängt und konsummiert. Diese Idee habe ich irgendwo im Intetnet gelesen.

    Wenn das so ist, kann man dem Debugger beibringen, dies nicht zu tun? Die Tips, die ich dabei gefunden habe, haben bis jetzt nicht geholfen.

    Ich bin für jeden Tip dankbar.

    Gruß,
    Permana



  • Permana schrieb:

    ...
    Wenn das so ist, kann man dem Debugger beibringen, dies nicht zu tun? Die Tips, die ich dabei gefunden habe, haben bis jetzt nicht geholfen.

    Jemand hat geschrieben:
    "Ich mußte unter BBC++4.0 [I]nur[/] folgendes deaktivieren:
    Integrierte Fehlerbehandlung zulassen (o.ä.)"

    wo steht diese Option? Weiss das jemand? Ich habe Builder verison 6.



  • Permana schrieb:

    ich kann in den Logfiles meiner COM-Schnittstelle sehen, dass Exception geworfen wird.

    16.07.2010 17:22:29.238 E EXCEPTION GlobalExceptionHandler: Unerwartete Excpeption: System.InvalidCastException: Die angegebene Umwandlung ist ungültig.

    Das bedeutet, dass der C++ Builder, also vermutlich der Debugger diese Exceptions fängt und konsummiert.

    Eher nicht. Wenn du beim direkten Aufruf der COM-Schnittstelle "Der Vorgang wurde erfolgreich abgeschlossen" zurückbekommst, dann passiert die Exception gar nicht erst die COM-"Grenze"; der Fehler ist also auf der .NET-Seite.

    Du könntest mal versuchen, nicht die Late-binding-Schnittstelle zu verwenden. Ob du den Header herausgeben darfst, ist natürlich fragwürdig, aber könntest du mal (nur namentlich, inkl. Vorfahren) auflisten, welche Klassen und Interfaces alles in dem Header deklariert werden? Möglichst mit dem vom Importer generierten Kommentar darüber.

    Wenns zu viele sind, dann natürlich nur diejenigen, die mit dem, was du benutzen willst, in namentlicher Verbindung zu stehen scheinen.



  • Permana schrieb:

    Jemand hat geschrieben:
    "Ich mußte unter BBC++4.0 [I]nur[/] folgendes deaktivieren:
    Integrierte Fehlerbehandlung zulassen (o.ä.)"

    wo steht diese Option? Weiss das jemand? Ich habe Builder verison 6.

    Mannomann, die Drama geht weiter. Natürlich ist dieses Kästchen zum Hacken sehr einfach zu finden. Bei Debuuger-Optionen links unten. Leider bewirkt dies, dass man gar nicht mehr debuggen kann.

    Dann steht weiter bei "BS Exceptions" zur Auswahl, ob Exceptions von Applikation oder Debugger behandelt werden. Ist das nicht eine sehr offensichtliche Sache? Ja, doch. Bei unserer Konfiguration ist "Anwendungsprogramm" gewählt. Nur das hilft trotzdem nicht. Exceptions gehen mir verloren. 😡

    Ich setze Breakpoints an den Zeilen von utilcls_oleexc.cpp und der Debugger lehnt sie alle als ungültig ab. Also habe ich die Lösung von aucidia eigentlich noch gar nicht vollständig realisiert. 👎



  • audacia schrieb:

    ...dann passiert die Exception gar nicht erst die COM-"Grenze"; der Fehler ist also auf der .NET-Seite.

    Du könntest mal versuchen, nicht die Late-binding-Schnittstelle zu verwenden.

    ...(nur namentlich, inkl. Vorfahren) auflisten, welche Klassen und Interfaces alles in dem Header deklariert werden? Möglichst mit dem vom Importer generierten Kommentar darüber....

    Vielen Dank für Deine Aufmerksamkeit. Ich werde da einen Text vorbereiten.

    Was Early-Binding angeht, muss ich noch ein bischen studieren. :p



  • Sorry, ich muss etwas korrigieren. Ich bin übermüde und habe das Logfile zu früh aufgemacht. Die weiteren Versuche zeigen, dass die COM-Schnittstelle doch keine Exception verzeichnet. D.h. nicht mit unserer Applikation.

    Im Falle von Demo-App doch.

    Und beide Codes sind in C++.

    Da muss ich vermutlich mich ernsthaft um Late und Early Bindung kümmern.



  • audacia schrieb:

    Ob du den Header herausgeben darfst, ist natürlich fragwürdig, aber könntest du mal (nur namentlich, inkl. Vorfahren) auflisten, welche Klassen und Interfaces alles in dem Header deklariert werden? Möglichst mit dem vom Importer generierten Kommentar darüber.

    Wenns zu viele sind, dann natürlich nur diejenigen, die mit dem, was du benutzen willst, in namentlicher Verbindung zu stehen scheinen.

    Hi,

    ich freue mich weiterhin auf Feedback und habe nun das File in reduzierter Form vorbereitet. Bitte schön:

    #pragma option push -b -w-inl
    
    #include <utilcls.h>
    #if !defined(__UTILCLS_H_VERSION) || (__UTILCLS_H_VERSION < 0x0600)
    //
    // Der Code, der durch das Utility TLIBIMP oder den Import einer einer Typbibliothek 
    // und ActiveX-Funktion von C++Builder erezugt wird, basiert auf bestimmten Versionen 
    // der Header-Datei UTILCLS.H, die sich im Verzeichnis INCLUDE\VCL befindet. Wird eine 
    // ältere Version dieser Datei ermittelt, bentöigen Sie einen Update/Patch.
    //
    #error "Diese Datei erfordert eine neuere Version der Header-Datei UTILCLS.H" \
           "Sie müssen einen Update/Patch für Ihre Kopie von C++Builder durchführen"
    #endif
    #include <olectl.h>
    #include <ocidl.h>
    #if defined(USING_ATLVCL) || defined(USING_ATL)
    #if !defined(__TLB_NO_EVENT_WRAPPERS)
    #include <atl/atlmod.h>
    #endif
    #endif
    
    // *********************************************************************//
    // Forward-Referenz einiger VCL-Typen (zur Vermeidung der Einbeziehung von STDVCL.HPP)    
    // *********************************************************************//
    namespace Stdvcl {class IStrings; class IStringsDisp;}
    using namespace Stdvcl;
    typedef TComInterface<IStrings> IStringsPtr;
    typedef TComInterface<IStringsDisp> IStringsDispPtr;
    
    namespace XXXXX_tlb
    {
    // *********************************************************************//
    // Hilfe-String: YYYYY Type Library Version 1.0
    // Version:    1.0
    // *********************************************************************//
    
    // *********************************************************************//
    // In dieser Typbibliothek deklarierte GUIDS . Es werden folgende         
    // Präfixe verwendet:                                                     
    //   Typbibliotheken     : LIBID_xxxx                                     
    //   CoClasses          : CLSID_xxxx                                      
    //   DISPInterfaces     : DIID_xxxx                                       
    //   Nicht-DISP-Schnittstellen: IID_xxxx                                        
    // *********************************************************************//
    extern __declspec (package) const GUID IID_IYYYYY;
    extern __declspec (package) const GUID CLSID_YYYYY;
    
    interface DECLSPEC_UUID("{BF3D4B02-7CA7-3448-9D8E-02239F917AA0}") IYYYYY;
    typedef TComInterface<IYYYYY, &IID_IYYYYY> IYYYYYPtr;
    
    // *********************************************************************//
    // Deklaration von in der Typbibliothek definierten CoClasses             
    // (HINWEIS: Hier wird jede CoClass zu ihrer Standardschnittstelle        
    // zugewiesen)                                                            
    //                                                                        
    // Die Makros LIBID_OF_ weisen eine LIBID_OF_CoClassName zur GUID dieser  
    // Typbibliothek zu. Dies erleichtert die Aktualisierung von Makros bei   
    // der Änderung von Makronamen.                                           
    // *********************************************************************//
    typedef IYYYYY YYYYY;
    typedef IYYYYYPtr YYYYYPtr;
    
    #define LIBID_OF_YYYYY (&LIBID_XXXXX)
    
    // *********************************************************************//
    // Schnittstelle: IYYYYY
    // Flags:     (4432) Hidden Dual OleAutomation Dispatchable
    // *********************************************************************//
    interface IYYYYY  : public IDispatch
    {
    public:
      // [9] Ermöglicht den Zugriff auf die Benuteroberflächeneigenschaften.
      virtual HRESULT STDMETHODCALLTYPE get_GraphicalUserInterface(XXXXX_tlb::IGraphicalUserInterface** retval/*[out,retval]*/) = 0;
      // [10] Laden einer vollständigen Arbeitsumgebung(Messkonfig, OnlineVis, Scripts,...).
      virtual HRESULT STDMETHODCALLTYPE OpenWorkspace(BSTR fileName/*[in]*/) = 0;
      // [7] Zeigt die Programmoberfläche.
      virtual HRESULT STDMETHODCALLTYPE Show(void) = 0;
    
    #if !defined(__TLB_NO_INTERFACE_WRAPPERS)
    
      XXXXX_tlb::IGraphicalUserInterface* __fastcall get_GraphicalUserInterface(void)
      {
        XXXXX_tlb::IGraphicalUserInterface* retval;
        OLECHECK(this->get_GraphicalUserInterface((XXXXX_tlb::IGraphicalUserInterface**)&retval));
        return retval;
      }
    
      __property   XXXXX_tlb::IGraphicalUserInterface* GraphicalUserInterface = {read = get_GraphicalUserInterface};
    
    #endif //   __TLB_NO_INTERFACE_WRAPPERS
    
    };
    // *********************************************************************//
    // SmartIntf: TCOMIYYYYY
    // Schnittstelle: IYYYYY
    // *********************************************************************//
    template <class T /* IYYYYY */ >
    class TCOMIYYYYYT : public TComInterface<IYYYYY>, public TComInterfaceBase<IUnknown>
    {
    public:
      TCOMIYYYYYT() {}
      TCOMIYYYYYT(IYYYYY *intf, bool addRef = false) : TComInterface<IYYYYY>(intf, addRef) {}
      TCOMIYYYYYT(const TCOMIYYYYYT& src) : TComInterface<IYYYYY>(src) {}
      TCOMIYYYYYT& operator=(const TCOMIYYYYYT& src) { Bind(src, true); return *this;}
    
      HRESULT         __fastcall get_GraphicalUserInterface(XXXXX_tlb::IGraphicalUserInterface** retval/*[out,retval]*/);
      HRESULT         __fastcall get_GraphicalUserInterface(XXXXX_tlb::IGraphicalUserInterfacePtr* retval/*[out,retval]*/);
      XXXXX_tlb::IGraphicalUserInterfacePtr __fastcall get_GraphicalUserInterface(void);
      HRESULT         __fastcall OpenWorkspace(BSTR fileName/*[in]*/);
      HRESULT         __fastcall Show(void);
    
      __property   XXXXX_tlb::IGraphicalUserInterfacePtr GraphicalUserInterface = {read = get_GraphicalUserInterface};
    
    };
    typedef TCOMIYYYYYT<IYYYYY> TCOMIYYYYY;
    
    // *********************************************************************//
    // DispIntf:  IYYYYY
    // Flags:     (4432) Hidden Dual OleAutomation Dispatchable
    // *********************************************************************//
    template<class T>
    class IYYYYYDispT : public TAutoDriver<IYYYYY>
    {
    public:
      IYYYYYDispT(){}
    
      IYYYYYDispT(IYYYYY *pintf)
      {
        TAutoDriver<IYYYYY>::Bind(pintf, false);
      }
    
      IYYYYYDispT(IYYYYYPtr pintf)
      {
        TAutoDriver<IYYYYY>::Bind(pintf, true);
      }
    
      IYYYYYDispT& operator=(IYYYYY *pintf)
      {
        TAutoDriver<IYYYYY>::Bind(pintf, false);
        return *this;
      }
    
      IYYYYYDispT& operator=(IYYYYYPtr pintf)
      {
        TAutoDriver<IYYYYY>::Bind(pintf, true);
        return *this;
      }
    
      HRESULT BindDefault()
      {
        return OLECHECK(Bind(CLSID_YYYYY));
      }
    
      HRESULT BindRunning()
      {
        return BindToActive(CLSID_YYYYY);
      }
    
      XXXXX_tlb::IScriptingWorkspace* __fastcall get_ScriptingWorkspace(void);
      HRESULT         __fastcall get_GraphicalUserInterface(XXXXX_tlb::IGraphicalUserInterface** retval/*[out,retval]*/);
      XXXXX_tlb::IGraphicalUserInterface* __fastcall get_GraphicalUserInterface(void);
      HRESULT         __fastcall OpenWorkspace(BSTR fileName/*[in]*/);
      HRESULT         __fastcall Show();
    
      XXXXX_tlb::IUserSettings* __fastcall get_UserSettings(void);
    
      __property   XXXXX_tlb::IGraphicalUserInterface* GraphicalUserInterface = {read = get_GraphicalUserInterface};
    
    };
    typedef IYYYYYDispT<IYYYYY> IYYYYYDisp;
    
    // *********************************************************************//
    // SmartIntf: TCOMIYYYYY
    // Schnittstelle: IYYYYY
    // *********************************************************************//
    template <class T> HRESULT __fastcall
    TCOMIYYYYYT<T>::get_GraphicalUserInterface(XXXXX_tlb::IGraphicalUserInterface** retval/*[out,retval]*/)
    {
      return (*this)->get_GraphicalUserInterface(retval);
    }
    
    template <class T> HRESULT __fastcall
    TCOMIYYYYYT<T>::get_GraphicalUserInterface(XXXXX_tlb::IGraphicalUserInterfacePtr* retval/*[out,retval]*/)
    {
      return (*this)->get_GraphicalUserInterface(IGraphicalUserInterface**)retval);
    }
    
    template <class T> XXXXX_tlb::IGraphicalUserInterfacePtr __fastcall
    TCOMIYYYYYT<T>::get_GraphicalUserInterface(void)
    {
      XXXXX_tlb::IGraphicalUserInterface* retval;
      OLECHECK(this->get_GraphicalUserInterface((XXXXX_tlb::IGraphicalUserInterface**)&retval));
      return (XXXXX_tlb::IGraphicalUserInterfacePtr)retval;
    }
    
    template <class T> HRESULT __fastcall
    TCOMIYYYYYT<T>::OpenWorkspace(BSTR fileName/*[in]*/)
    {
      return (*this)->OpenWorkspace(fileName);
    }
    
    template <class T> HRESULT __fastcall
    TCOMIYYYYYT<T>::Show(void)
    {
      return (*this)->Show();
    }
    
    // *********************************************************************//
    // DispIntf:  IYYYYY
    // Flags:     (4432) Hidden Dual OleAutomation Dispatchable
    // *********************************************************************//
    template <class T> HRESULT __fastcall
    IYYYYYDispT<T>::get_GraphicalUserInterface(XXXXX_tlb::IGraphicalUserInterface** retval/*[out,retval]*/)
    {
      _TDispID _dispid(*this, OLETEXT("GraphicalUserInterface"), DISPID(9));
      TAutoArgs<0> _args;
      return OutRetValSetterPtr((LPDISPATCH*)(XXXXX_tlb::IGraphicalUserInterface**)retval /*[VT_USERDEFINED:2]*/, _args, OlePropertyGet(_dispid, _args));
    }
    
    template <class T> XXXXX_tlb::IGraphicalUserInterface* __fastcall
    IYYYYYDispT<T>::get_GraphicalUserInterface(void)
    {
      XXXXX_tlb::IGraphicalUserInterface* retval;
      this->get_GraphicalUserInterface((XXXXX_tlb::IGraphicalUserInterface**)&retval);
      return retval;
    }
    
    template <class T> HRESULT __fastcall
    IYYYYYDispT<T>::OpenWorkspace(BSTR fileName/*[in]*/)
    {
      _TDispID _dispid(*this, OLETEXT("OpenWorkspace"), DISPID(10));
      TAutoArgs<1> _args;
      _args[1] = fileName /*[VT_BSTR:0]*/;
      return OleFunction(_dispid, _args);
    }
    
    template <class T> HRESULT __fastcall
    IYYYYYDispT<T>::Show()
    {
      _TDispID _dispid(*this, OLETEXT("Show"), DISPID(7));
      return OleFunction(_dispid);
    }
    
    };     // namespace XXXXX_tlb
    
    #if !defined(NO_IMPLICIT_NAMESPACE_USE)
    using  namespace XXXXX_tlb;
    #endif
    
    #pragma option pop
    


  • Permana schrieb:

    Ich setze Breakpoints an den Zeilen von utilcls_oleexc.cpp und der Debugger lehnt sie alle als ungültig ab. Also habe ich die Lösung von aucidia eigentlich noch gar nicht vollständig realisiert. 👎

    Das liegt daran, daß ich für dieses Unit die Debug-Info explizit deaktiviert habe (durch ein #pragma am Anfang der Datei), und das ist auch Sinn der Sache (sonst verwirrt dich der Debugger im Falle einer Exception, indem er in utilcls_oleexc.cpp landet). Und mein Benutzername ist audacia.

    Permana schrieb:

    ich freue mich weiterhin auf Feedback und habe nun das File in reduzierter Form vorbereitet. Bitte schön:
    [...]

    Ah, das ist hilfreich. Der Header definiert also sowohl ein Early-binding- als auch ein Late-binding-Interface. Das Early-binding-Interface verwendest du, indem du einfach TCOMIYYYYY anstelle von IYYYYYDisp benutzt. Der korrekte Weg, um HRESULT-Rückgabewerte explizit zu überprüfen, ist dann

    CheckSafecallResult (OpenWorkspace (WideString (someString).c_bstr ()));
    

    .
    Wenn du utilcls_oleexc.cpp eingebunden hast, kannst du statt CheckSafecallResult() auch OLECHECK() verwenden.



  • Hallo audacia,

    ich kann in unserem Code keinerlei Referenz zum Wort "IYYYYYDispT" finden.
    Daher verstehe ich dich nur begrentzt.

    Bis jetzt haben wir folgendes da und da im Code, was an sich für mich schlüssig ist:

    interface IYYYYY : public IDispatch { ... }
    IYYYYY m_XXXXX; //unser wichtigster Schlüsselpointer bis jetzt.
    extern __declspec (package) const GUID CLSID_YYYYY;
    HRESULT hr = CoInitialize(NULL);
    IUnknown pUnknown = NULL;
    hr = CoCreateInstance(CLSID_YYYYY , NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void
    )&pUnknown);
    hr = pUnknown->QueryInterface(IID_IYYYYY, (void**)&m_XXXXX);
    m_XXXXX->OpenWorkspace(StringToOleStr(myFileName));

    Meinst du nun, ich soll folgendes zum Code addieren?

    TCOMIYYYYY *myYYYYYCom;
    myYYYYYCom = new TCOMIYYYYY (m_XXXXX, false) // m_XXXXX kommt von oben.
    myYYYYYCom->OpenWorkspace(StringToOleStr(myFileName));

    Vielleicht fehlt mir Wissen von COM Technology. Wie bringe ich IYYYYY in Verbindung mit TCOMIYYYYY? Und welcher Parameter hat bis jetzt den Weg zu IYYYYYDisp geebnet?

    Gruß,
    Permana



  • Permana schrieb:

    Bis jetzt haben wir folgendes da und da im Code, was an sich für mich schlüssig ist:

    interface IYYYYY : public IDispatch { ... }
    IYYYYY m_XXXXX; //unser wichtigster Schlüsselpointer bis jetzt.
    extern __declspec (package) const GUID CLSID_YYYYY;
    HRESULT hr = CoInitialize(NULL);
    IUnknown pUnknown = NULL;
    hr = CoCreateInstance(CLSID_YYYYY , NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void
    )&pUnknown);
    hr = pUnknown->QueryInterface(IID_IYYYYY, (void**)&m_XXXXX);

    Uah.
    Du benutzt bereits das Early-binding-Interface. Ich dachte, du würdest Late Binding verwenden, weil ich mich an deinen Post erinnerte:

    Permana schrieb:

    audacia schrieb:

    Könntest du mal die Deklaration von OpenWorkspace() in der Headerdatei zeigen?

    Hilft dies aus dem Headerfile der automatisch erzeugte Typelibrary?

    (mit
    typedef LONG HRESULT;)
    HRESULT __fastcall OpenWorkspace(BSTR fileName/[in]/);

    template <class T> HRESULT __fastcall
    IBlablaBlaDispT<T>::OpenWorkspace(BSTR fileName/[in]/)
    {
    _TDispID _dispid(this, OLETEXT("OpenWorkspace"), DISPID(10));
    TAutoArgs<1> _args;
    _args[1] = fileName /
    [VT_BSTR:0]*/;
    return OleFunction(_dispid, _args);
    }

    Die Funktionsdefinition, die du da zitiert hast, ist fürs Late-binding-Interface gedacht, daher dachte ich, daß du sie auch verwendest 😉

    Permana schrieb:

    Meinst du nun, ich soll folgendes zum Code addieren?
    [...]

    Nein. Bisher scheinst du in der Handhabung von COM der Visual C++-Variante zu folgen (vermutlich weil deine Code-Beispiele für Visual C++ gedacht sind). Das geht in C++Builder zwar auch, aber es ist sehr viel umständlicher als nötig. In C++Builder würde folgender Code

    IYYYYY *m_XXXXX; //unser wichtigster Schlüsselpointer bis jetzt.
    extern __declspec (package) const GUID CLSID_YYYYY;
    HRESULT hr = CoInitialize(NULL);
    IUnknown *pUnknown = NULL;
    hr = CoCreateInstance(CLSID_YYYYY , NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&pUnknown);
    hr = pUnknown->QueryInterface(IID_IYYYYY, (void**)&m_XXXXX);
    m_XXXXX->OpenWorkspace(StringToOleStr(myFileName));
    

    zu dem hier (allerdings ungetestet, da ich deine Typbibliothek nicht habe):

    TCOMIAccessible m_XXXXX = CoYYYYY::Create ();
        CheckSafecallResult (m_XXXXX.OpenWorkspace(WideString (myFileName).c_bstr ()));
    

    Am Ende deiner Typbibliothek müßte ein CoClass-Wrapper für das Automationsobjekt zu finden sein, etwa so etwas:

    // *********************************************************************//
    // COCLASS STANDARD-INTERFACE ERZEUGUNG
    // CoClass : YYYYY
    // Interface: TCOMIYYYYY
    // *********************************************************************//
    typedef TCoClassCreatorT<TCOMIYYYYY, IYYYYY, &CLSID_YYYYY, &IID_IYYYYY> CoYYYYY;
    

    Diese CoClass vereinfacht die Erstellung von COM-Objekten signifikant.

    Wenn du das machst, im Normalfall alles funktioniert und immer Fehlerfall immer noch keine Exception auftritt, dann wird auf der anderen Seite auch keine geworfen, und es liegt in irgendeiner Weise an der Benutzung. Jedenfalls gibt es keinen Weg mehr, auf dem C++Builder die Exception irgendwie "verschlucken" könnte.



  • Ich habe folgendes an die richtigen Plätze gebracht und leider nur Access Violation Exception erhalten, was vermutlich nur eine interne Exception ist.

    hr = CoCreateInstance(CLSID_YYYYY , NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&pUnknown);
    TCOMIAccessible m_XXXXX = CoYYYYY::Create ();
    (m_XXXXX.OpenWorkspace(WideString (myFileName).c_bstr ()));

    CheckSafecallResult musste ich raus lassen, weil
    [Linker Fehler] Unresolved external 'System::__linkproc__ __fastcall CheckAutoResult()' referenced from C:\PROGRAM FILES\BORLAND\CBUILDER6\LIB\RELEASE\VCLE.LIB|syssupp

    Mittlerweile habe ich der Liferfirma geschrieben, wie sie sich unterschiedliche COM Traces im Falle von C# und C++ Applikation erklären.

    Gruß,
    Permana



  • Permana schrieb:

    hr = CoCreateInstance(CLSID_YYYYY , NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&pUnknown); 
    TCOMIAccessible m_XXXXX = CoYYYYY::Create (); 
    (m_XXXXX.OpenWorkspace(WideString (myFileName).c_bstr ()));
    

    Die erste Zeile ist, wenn ich es richtig sehe, überflüssig. In der zweiten Zeile habe ich einen Fehler gemacht: es muß natürlich nicht TCOMIAccessible, sondern TCOMIYYYYY heißen.

    Was die AV angeht: könntest du - nach Berichtigung obengenannter Fehler - einmal zeigen, wie die entsprechende Stelle deines Programmcodes wirklich aussieht?

    Permana schrieb:

    CheckSafecallResult musste ich raus lassen, weil
    [Linker Fehler] Unresolved external 'System::__linkproc__ __fastcall CheckAutoResult()' referenced from C:\PROGRAM FILES\BORLAND\CBUILDER6\LIB\RELEASE\VCLE.LIB|syssupp

    Das ist ein Bug in C++Builder 6, der in C++Builder 2006 behoben wurde. (Ein typisches Problem, wenn man mit acht Jahre alter Software arbeitet: man kämpft andauernd mit Problemen, die eigentlich längst behoben wurden. => Gelegentlich über ein Upgrade nachdenken.) Du kannst es folgendermaßen selbst beheben (irgendwo in deinem Quellcode einzufügen):

    #pragma alias "@System@CheckSafecallResult$qqrl" \
          = "@System@@CheckAutoResult$qqrl"
    


  • Hallo audacia,

    ich habe Deine Korrekturen berücksichtigt. Es ging dann glatt.
    Leider wieder ohne Exception. Langsam langsam bleibt mir nur der Glaube, dass da keine Exceptions geworfen werden.

    Ich habe zufällig auch ein kleines Testprogramm in C++, das in Visual Studio
    läuft. Da fällt das Progrämmchen in Exceptionzweig a la catch(...). Ich weiss
    bisher keine Exceptionname, was ich da rein schreiben könnte, um die Botschaft
    auszulesen, um sicher zu sein, dass es sich um meine Exception wegen dem bösen
    Workspacefile handelt (und keine andere).

    Es ist sehr nett, dass du so viel Geduld bisher mit mir gehabt hast. Ich warte
    nebenbei auf die Antwort der Interfaceentwickler.

    viele Grüsse,
    Permana



  • Permana schrieb:

    ...
    Ich habe zufällig auch ein kleines Testprogramm in C++, das in Visual Studio
    läuft. Da fällt das Progrämmchen in Exceptionzweig a la catch(...).
    ...
    Es ist sehr nett, dass du so viel Geduld bisher mit mir gehabt hast. Ich warte
    nebenbei auf die Antwort der Interfaceentwickler.

    Die Lieferantenfirma hat nichts besseres zu sagen, außer daß ich catch(...) einsetzen sollte, was natürlich einer der ersten Schritte ist, die ich unternommen habe.

    Ich glaube, wir brauchen neue Compiler und Umgebung.

    Gruß,
    Permana


Anmelden zum Antworten