Sitzungsübergreifender Shared Memory Block



  • Hi zusammen,

    ich habe folgende Anforderung:
    Ein Anwendung kann sowohl als normale Desktopapplikation als auch als Windows Service laufen. Um das mehrfache Ausführen zu verhindern habe ich mir überlegt, die Anwendung durch einen shared memory Block zu identifizieren. Der shared memory Block besteht aus einer 32bit Prozess- und einer 32bit Thread-Id. Der shared memory Block ist benannt und trägt den Namen "InstanceLock".
    Ich benutze boost::interprocess::windows_shared_memory, das intern die WINAPI und die Funktion CreateFileMapping benutzt.

    Die Anwendung wird als Desktop-Anwendung gestartet:
    Die Anwendung prüft, ob es einen shared memory Block mit einem bestimmten Namen gibt. Wenn das der Fall ist, liest sie die Prozess- und Thread-ID aus, und vergleicht die gelesene Prozess-Id mit ihrer eigenene Prozess-Id. Wenn die beiden unterschiedlich sind ist die Anwendung nicht Erzeuger des shared memory Blocks, damit nicht Besitzer und beendet sich.
    So weit, so gut, funktioniert innerhalb der gleichen Windows-Sitzung.

    Jetzt wird die Anwendung als Windows Service gestartet. Laut MSDN verhält sich da CreateFileMapping anders, indem es dem shared memory Namen den Präfix Global\ voranstellt, aus "InstanceLock" wird also Global\InstanceLock. Wenn die Anwendung als Desktop-Anwendung gestartet wird sucht sie natürlich nach "InstanceLock", findet nichts und geht dann davon aus, dass sie die einzige Instanz ist und läuft brav weiter.

    Naive Idee: Generell den Namen auf "Global\InstanceLock" zu ändern, damit sich Service und Desktopanwendung absprechen können. Funktioniert prima, wenn der Service den shared memory Block anlegt. Funktioniert leider nicht mehr so gut, wenn es die Desktop-Anwendung tun soll, denn die braucht jetzt Administrator-Rechte, das Aktivieren des Privilegs "SeCreateGlobal" reicht leider nicht aus.

    Auch wenn die Verriegelung sitzungsübergreifend sein soll, d.h. wenn Benutzer A mit seinen Kontoinformationen die Anwendung startet wird das für Benutzer B nur dann erkannt, wenn der shared memory Block im "Global" Namespace angelegt worden ist.

    Weiß jemand, wie ich die Anforderung für Adminrechte umgehen kann, damit die Anwendung Objekte im "Global" Namespace anlegen kann?



  • Ich hab nur die Antwort die du nicht hören willst: lass immer das Service laufen.



  • @DocShoe
    Und wie sieht dies mit OpenMutex und CreateMutex aus?



  • @hustbaer sagte in Sitzungsübergreifender Shared Memory Block:

    Ich hab nur die Antwort die du nicht hören willst: lass immer das Service laufen.

    Stimmt 😉

    @Quiche-Lorraine sagte in Sitzungsübergreifender Shared Memory Block:

    @DocShoe
    Und wie sieht dies mit OpenMutex und CreateMutex aus?

    Habe ich nicht ausprobiert, aber laut meiner oben verlinkten Doku zu den Kernel Object Names sollen alle benannten Objekte den "Global" Präfix bekommen, wenn sie von einem Service erzeugt werden.
    Aber selbst wenn ein benannter CreateMutex gelingen sollte hilft mir das nicht weiter, weil ich gerne die Prozess- und Thread-Id des Erzeugers hätte.

    Aber Danke für eure Antworten.


Anmelden zum Antworten