# Saturday, August 29, 2009

Eine Anwendung nur einmal öffnen

Gerade bin ich in Klaus’ Blog auf einen Post gestoßen, der mich etwas irritiert hat. Im deutschen stackoverflow.com tauchte die Frage auf, wie man eine Anwendung so gestalten kann, dass sie nur einmal gestartet werden darf. Dafür nimmt ja bekanntlich einen Mutex, da dieses Verriegelungsobjekt systemweite Gültigkeit hat und daher zwar nicht explizit für diesen Fall geschaffen wurde, sich aber am besten von allen Verriegelungsobjekten dafür eignet.

Klaus präsentiert jedoch einen Vorschlag, den er persönlich besser findet. Er ermittelt über die statische Methode Process.GetProcesses alle im System vorhandenen Prozesse und sucht dann den Prozess, der den Namen seiner Anwendung trägt. Warum er Mutexe meidet und lieber über alle Prozesse iteriert, sagt er leider nur in einem Kommentar:

Mit Kanonen auf Spatzen ist da noch untertrieben.[..]

Auf Peter Buchers Kommentar, man möge doch einen Mutex verwenden Antwortet Klaus:

Hallo Peter,
ich weiß dass viele den Mutex bemühen. Doch gerade die Verwendung eines Mutex, und er muss als System-Mutex registriert werden, verlangt einiges an Disziplin. Der Mutex muss sauber gegen Exceptions abgesichert werden, er muss auf alle Fälle freigegeben werden und der Benutzer muss über die nötigen Rechte verfügen.
Um all das zu umgehen, hab ich mir diese einfache "use and forget" Methode überlegt.

Allerdings ist es nicht die Vorgehensweise, einen Mutex zu verwenden (je nach verwendetem Konstruktor), sondern seine eigene, bei der der Benutzer über die nötigen Rechte verfügen muss.

Die Methode Process.GetProcesses erfordert vollen Systemzugriff, also muss die Anwendung in der Sicherheitsgruppe FullTrust ausgeführt werden.

Dass man sich bei Verriegelungsobjekten Gedanken darüber machen muss, wie man sie sauber freigibt, sollte in Zeiten des Multithreadings jedem Programmierer klar sein. Gegen Exceptions kann er über den globalen ExceptionHandler abgesichert werden, den ebenfalls jede Anwendung haben sollte, um Unhandled Exceptions protokollieren zu können. Bei einem sauberen Systemdesign ist der “Mit dem Kopf durch die Wand”-Methode von Klaus nicht unbedingt die einfachere Alternative.

In den letzten Jahren ist das Thema Sicherheit immer mehr in den Fokus gerückt. Microsoft versucht, die Programmierer von Windows-Software dazu zu bewegen, sich endlich an die Implementierungsvorschriften zu halten, damit es möglich werden kann, dass ein Windows-Benutzer nicht grundsätzlich Administrator sein muss, um seinen PC benutzen zu können. In diesen Zeiten kann ich den Hinweis von Klaus daher nicht unkommentiert stehen lassen, vor allem, da er nur einseitig eine Halbwahrheit beschreibt.

Saturday, August 29, 2009 9:33:00 AM (W. Europe Daylight Time, UTC+02:00) #  Comments [2] | Trackback
Saturday, September 26, 2009 3:29:19 PM (W. Europe Daylight Time, UTC+02:00)
Hallo Peter,
ich habe deinen Artikel leider erst heute entdeckt. Will aber trotzdem, wenn auch sehr verspätet, die Gelegenheit nutzen um auf ein paar deiner Feststellungen einzugehen.
du sagst hier aus, Zitat:
"Allerdings ist es nicht die Vorgehensweise, einen Mutex zu verwenden (je nach verwendetem Konstruktor), sondern seine eigene, bei der der Benutzer über die nötigen Rechte verfügen muss.
Die Methode Process.GetProcesses erfordert vollen Systemzugriff, also muss die Anwendung in der Sicherheitsgruppe FullTrust ausgeführt werden."

Dabei beziehst du dich auf die Dokumentation in der MSDN. Wenn du dir die Mühe machen würdest und die aktuelle Version der Dokumentation liest, wirst du beim Gegenüberstellen der Berechtigungen sehen, dass da de facto kein Unterschied zwischen beiden Verfahren besteht. Zitat MSDN zur Implementierung von Process.GetProcess:
"LinkDemand
für volle Vertrauenswürdigkeit für den unmittelbaren Aufrufer. Dieser Member kann nicht von teilweise vertrauenswürdigem Code verwendet werden."

und zur Gegenüberstellung die Methode Mutex.OpenExisting, beide Überladungen:
"SecurityPermission
zum Aufrufen von nicht verwaltetem Code, damit ein benannter Mutex erstellt werden kann. Zugeordnete Enumeration: SecurityPermissionFlag.UnmanagedCode.

Sicherheitsaktion: LinkDemand."

Wie du sehen kannst verlangen beide Verfahren von der aufrufenden Methode volles Vertrauen um ausgeführt werden zu können. Dass beide absolut nichts mit administrativen Rechten des Benutzers zu tun haben, sollte dir jetzt klar sein.

Wie ich volgende Aussage von dir verstehen soll, entzieht sich meinem Verständniss:
"Bei einem sauberen Systemdesign ist der “Mit dem Kopf durch die Wand”-Methode von Klaus nicht unbedingt die einfachere Alternative."

Ich habe weder ein Sicherheitsloch aufgerissen, moch sehe ich einen anderen Verstoß gegen ein "sauberes Systemdesign". Auch was du "mit dem kopf durch die Wand" meinst ist mir nicht ganz klar.

Zu dieser von dir getroffenen Aussage:
"... damit es möglich werden kann, dass ein Windows-Benutzer nicht grundsätzlich Administrator sein muss, um seinen PC benutzen zu können. In diesen Zeiten kann ich den Hinweis von Klaus daher nicht unkommentiert stehen lassen, vor allem, da er nur einseitig eine Halbwahrheit beschreibt."

Kann ich nur sagen: Hättest du dir die Mühe gemacht und mein Beispiel auch nur einmal ausgeführt, währe dir aufgefallen dass definitiv keine Administratorrechte erforderlich sind.
Ich arbeite unter Vista immer mit aktivierter UAC und auch Visual Studio läuft nicht im Administratorkontext.

Servus,
Klaus

P.S. Könntest du bitte den "halben Kommentar" über diesem löschen?
Friday, February 26, 2010 2:41:51 PM (W. Europe Standard Time, UTC+01:00)
Hallo Klaus,

Ich habe Mutex.OpenExisting nachgeschlagen. Allerdings nicht wie du in Version 3.5 des .NET Frameworks, sondern in Version 2.0. Dort ist kein Verweis darauf zu finden, dass die Funktion ur von vollvertrauenswürdigen Code aufgerufen werden darf.

"Mit dem Kopf durch die Wand" nenne ich deine Vorschlag deshalb, weil er die Namen der Prozesse mit dem aktuell verwendeten vergleicht. Dies birgt das Risiko, dass ein Prozess nicht gefunden wird, wenn der Name nicht exakt stimmt. In Anbetracht dessen, dass es einige Anwendungen gibt, die ihre Versionsnummer im Prozessnamen tragen, könnte es hier zu Problemen kommen.

Den halben Kommentar habe ich entfernt. :)

mfG, Peter
OpenID
Please login with either your OpenID above, or your details below.
Name
E-mail
Home page

Comment (Some html is allowed: a@href@title, strike) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Live Comment Preview