COM Surrogate bzw. LOCAL_SERVER


  • Mod

    Ich habe mich aus Neugierde nochmal in das Thema eingelesen.
    Eigentlich müsste bei Verwendung des DLLHosts in jedem Flall ein und dieselbe DLL für alle Instanzen verwendet werden.

    Eigentlich haben viele eher das umgekehrte Problem wie ich gelesen habe. Viele wollen mehrere Instanzen Out of Process....



  • Hallo Martin,

    danke erstmal. Also ja, dieselbe DLL wird auf jeden Fall verwendet. Aber hier kommt es jetzt wohl auf die Nomenklatur an. Es werden dennoch 2 unterschiedliche Objekte von der ClassFactory, die da surrogiert wird, erzeugt.

    Mein Code sieht jetzt gerade so aus:

    _com_ptr_t<_com_IIID<IClassFactory, &__uuidof(IClassFactory)>> class_factory_ptr;
    HRESULT hr = CoGetClassObject(CLSID_Object, CLSCTX_LOCAL_SERVER, 0,IID_IClassFactory, (void**)static_cast<IClassFactory**>(&class_factory_ptr) );
    if(FAILED(hr))
    {
        bool arrrrr = true;
    } else {
        class_factory_ptr.GetInterfacePtr()->CreateInstance( NULL, IID_Object, (void**)static_cast<IObject**>(&object_ptr) );
    }
    

    Es macht jetzt auch gar keinen Unterschied, ob ich überhaupt den Umweg über die ClassFactory mache, ich bekomme immer das IObject*-Interface zu zwei verschiedenen Objekten.
    Vielleicht ist ja auch an meinem COM-Code etwas grundlegend falsch? CLSID_Object und IID_Object sind auf jeden Fall die GUIDs aus der .tlh-Datei, die #import erzeugt.


  • Mod

    Na dann tippe ich mal darauf, dass Deine DLL die Classfactory mit REGCLS_SINGLEUSE oder REGCLS_MULTI_SEPARATE registriert.



  • Hey,

    vielleicht denke ich gerade viel zu C++-Objektorientiert. Aber ich stelle mir das gerade so vor, dass dieses Flag nur anzeigt, ob man dieselbe Instanz der Factory erhält? Will meinen: man hat ja so auch keinen Einfluss darauf, in welcher Art die Factory selber dann die benötigten Interfaces "beschafft"?

    Oder anders ausgedrückt: Ich stelle mir so eine Factory gerade so vor, wie ich mir eben eine Factory als Pattern im eigenen C++-Code vorstelle. Die Schnittstelle sagt ja dort auch nichts über konkrete Zusammenhänge mit Objekten aus. Dort könnte man also auch speziell eine SingletonFactory implementieren, aber sieht ja der Schnittstelle nicht an, was eine abstrakte Factory dann tut.

    Woher kommt eigentlich die IClassFactory-Schnittstelle in der dll? Also so wie es für mich aussieht, handelt es sich bei meiner dll um eine von VB6 erzeugte. Hat der Programmierer da selber eine ClassFactory programmieren müssen, oder wird die ClassFactory automatisch aus den Schnittstellenbeschreibungen der VB-Klassen generiert und dort hätte man schon zur Zeit der DLL-Erstellung angeben müssen, dass man gerne ein Singleton hätte?

    Und noch eine andere Frage: Gibt es eine Möglichkeit herauszufinden, was hinter den Marshalled LOCAL_SERVER-Interfaces steckt? Also ob in dem LOCAL_SERVER-Prozess dieselben Interfaces gemeint sind, auch wenn man in eigenen Prozessen unterschiedliche Zeiger halt?

    Viele Grüße,
    Deci


  • Mod

    Nein!
    REGCLS_SINGLEUSE bedeutet, dass die Factory nach der ersten Benutzung sich deregistriert... 😉

    After an application is connected to a class object with CoGetClassObject, the class object is removed from public view so that no other applications can connect to it. This value is commonly used for single document interface (SDI) applications. Specifying this value does not affect the responsibility of the object application to call CoRevokeClassObject; it must always call CoRevokeClassObject when it is finished with an object class.



  • Hrmmm, wenn dem so wäre, dann würde ich doch kein zweites Objekt von der Klasse erzeugen können? Man kann doch eigentlich nur eine Factory pro CLSID registrieren, will meinen, wenn sich jemand dieser ClassFactory besorgt, wird niemand zweites mehr eine Factory für diese Klasse bekommen.
    Aber ich habe ja zwei unterschiedliche Instanzen von IID_Object, also 2 unterschiedliche Objekte, aber beide von der gleichen Klasse (es gibt überhaupt nur eine Klasse auf meinem System, die das besagte IObject implementiert). Also muss ich doch zweimal die CLSID_Object-Factory benutzt haben, die mir das Objekt rausgehauen hat, das ich dann über IUnknown nach IID_Object gefragt habe?


  • Mod

    Das stimmt nicht. Weil keine Factory existiert wird eine zweite Instanz der DLL geladen. Es ist doch dann genauso, als wenn noch nie eine Instanz erzeugt wurde.

    Es werden doch nicht durch COM prophylaktisch alle Factories erzeugt. Das genau ist ja schon der Unterschied zum Factory Pattern.



  • Oh, ich hatte das jetzt so verstanden, dass COM die dll/exe halt on-demand wie in der Registry eingestellt lädt, aber dann diese eine dll das ist, was überall reingemapped wird oder im surrogate oder dem exe-Local-Server-Prozess läuft. Dass sozusagen die Factory immer wiederverwendet wird, es sei denn, das will man unterbinden, dann war's das mit der Klasse. Late-Loading oder wie man das bezeichnen sollte.
    Na gut, dann kann ich wohl von außen nichts weiter tun. Wer weiß, ob die ClassFactory überhaupt damit klar käme, dass man mehrmals CreateInstance aufruft, oder wenn ja, ob dann immer die selbe Instanz für das IObject-Interface rausgeschmissen würde...


  • Mod

    Der sicherste Weg ist es bestimmt. Das Ganze selbst zu wrappen, wie ich es beschrieben habe. Da es sich aber um ein Objekt handelt ist es natürlich dennoch spannend wie dann der Zugriff aus mehreren Interface Zeigern läuft.



  • Ach, die Schnittstelle ist einfach, was das eigentlich Objekt macht, ist auch total trivial. Mir wurde nur explizit untersagt, die dll durch eine reverse-engineered (ich zitiere: "hacked") Eigenentwicklung zu substituieren. Deswegen muss die Software jetzt also mit ein paar VB6-dlls und der COM-dll installiert werden. Synchronisation wird kein großes Problem. Schöne neue Welt! 😃


  • Mod

    Dann hast Du Dir die Antwort gegeben. Bau ein COM Singleton in einem out of process Server, der nichts anderes macht als dieses Objekt in die IROT zu legen.

    Dann können sich theoretisch sogar andere Prozesse dieses Objekt aus der IROT ziehen. Marshalling macht COM für Dich.



  • Das mit dem Singleton war jetzt der Plan, auch wenn ich jetzt noch nicht daran gedacht habe, IRunningObjectTable zu verwenden und mich erstmal über Moniker schlau lesen muss (hatte jetzt eigentlich vor, einen einfachen Wrapper drumzubasteln, andere CLSID, aber unterstützt dann eben auch IObject. Wollte nur noch ein bissl erzählen, statt hier einfach auf stumm zu schalten. Da freut sich meiner Erfahrung nach der Unterstützer mehr 😉


  • Mod

    🙂



  • Martin Richter schrieb:

    Dann hast Du Dir die Antwort gegeben. Bau ein COM Singleton in einem out of process Server, der nichts anderes macht als dieses Objekt in die IROT zu legen.

    Dann können sich theoretisch sogar andere Prozesse dieses Objekt aus der IROT ziehen. Marshalling macht COM für Dich.

    Was ist, wenn das Objekt aus der ROT an den Client zurückgegeben wurde? Wie funktioniert das mit der Referenzzählung, wie wird so die Lebensdauer des Prozesses kontrolliert? So einfach ist das nicht, meine ich jedenfalls momentan noch. Mir scheint, als müsstest Du die Schnittstelle für dieses Vorhaben exakt nachbauen, damit Du entsprechend CoAddRefServerProcess/CoReleaseServerProcess matchen kannst. Die implementierten Methoden delegieren dann einfach nur.

    Ich glaube fast, ich würde da einfach einen Dienst drumrum stricken. Die IClassFactory erstellt das Objekt und ruft in CreateInstance einfach QueryInterface auf. Endet der Dienst, gibt es ein einfaches CoDisconnectObject und gut. Und da der Client scheinbar ohnehin nur CoCreateInstance aufruft, bringt Dir die ROT außer Gefummel auch keine Vorteile.

    Falls ich völlig neben der Spur bin, bitte ich um Aufklärung!



  • ... oder man baut sich ein eigenes Surrogate, ISurrogate zum implementieren ist ja nun auch kein Hexenwerk. 🙂


Anmelden zum Antworten