So, ich habe eine Lösung gefunden:
Für jede Anwendung wird ein eindeutiger Name erzeugt, z.B. MyApplicationA Mit diesem Namen wird ein privater Namespace erzeugt, in dem jetzt Kernel Objects erzeugt werden können. Mein shared memory Block heisst jetzt MyApplicationA\InstanceLock, in den die Prozess- und Thread-Id des erzeugenden Prozesses geschrieben werden.
Wenn die Anwendung gestartet wird, versucht sie zuerst dieses Objekt zu finden und zu öffnen, wenn das gelingt, können die Prozessdaten des Erzeugers aus dem shared memory Block gelesen werden. Wenn das Objekt nicht gefunden werden kann, wird ein neuer shared memory Block mit den entsprechenden Informationen erzeugt.
Das Ganze funktioniert für einzelne Sitzungen, sitzungsübergreifend und auch für Windows Dienste.
Wenn gewünscht kann ich Quelltext Codeschnipsel posten, mit denen ich das realisiert habe.