Moderne Rechtestruktur

Behandelt die Probleme mit Rechten (Dateien schreiben, Registrierung bearbeiten) ab Windows Vista mit Visual Studio bis 2008.

Seit Windows Vista gibt es die sog. UAC (User Account Control), welche für mehr Sicherheit sorgen soll. Ob dieses Konzept gut oder sinnvoll ist bleibt dahingestellt, jedenfalls sorgt dieses neue Konzept dafür, dass viele (alte) Programme nicht mehr korrekt unter Windows Vista oder Windows 7 funktionieren.

Dieses Schicksal ereilte auch einige meiner Programme und so fing ich an tiefer nachzuforschen wie man das ganze geschickt umgehen kann. Ich werde hier einige wenige präsentieren, so dass es hier für jedes Problem mit der UAC die geeignete Lösung geben sollte.

1 | Dateien mit Einstellungen

Ich habe gerne die Einstellungsdateien für meine Programme selbst geschrieben. Einfach eine geeignete Klasse erstellt und Serialisiert - so wie man dies mit jedem eigenen Dateitypen machen würde. Die Frage die sich jedoch stellt ist: Wohin mit der Einstellungsdatei? Der Ort sollte zwei Aufgaben erfüllen

  • Für den Benutzer nicht auffallen / schon vorhanden sein.
  • Offensichtlich zum Programm gehören / nicht gelöscht werden.

Der in meinen Augen wohl geeignetste Ort war der Programmordner selbst. Sollte er gelöscht sein haben auch die Einstellungsdateien keine Verwendung mehr (und sind sowieso gelöscht), außerdem gehört er sehr offensichtlich zum Programm und stört den Benutzer auch nicht, da er sowieso weiß, dass es diesen Ordner gibt.

Diese Methode funktioniert ab Windows Vista nicht mehr, da Programme nur nach Erhalten eines Tokens von der UAC auf den "Program Files" Ordner - also den Ordner wo im Normalfall unter Windows Programm abgelegt werden - Schreibrechte erhalten.

Ich werde in diesem Abschnitt nicht diskutieren, wie man an ein solches Token kommt, sondern statt dessen einen neuen Ordner vorschlagen, der von Microsoft selbst für diese Aufgabe konzipiert wurde: der sog. "Common Application Data Folder".

Wie kommt man an diesen Ordner?

//Alter Code (Beispiel) [ Ausführungsverzeichnis ]
return string.Format("{0}\settings.xml", 
System.Reflection.Assembly.GetExecutingAssembly().Location));
//Neuer Code (Beispiel) [ Gemeinsame Daten ]
return string.Format("{0}\settings.xml", 
System.Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));

Jetzt liegen die Daten da so schön drin und sind doch relativ unerkenntlich für den interessierten Anwender. Man könnte nun einen Ordner erstellen, welcher alle (Einstellungs-) Dateien des Programms beinhaltet. Allerdings wär es geschickter dies gleich durch das Setup ausführen zu lassen. Möchte man dies über ein Visual Studio Setup Projekt durchführen so merkt man schnell, dass es im "Dateisystem-Editor" keinen speziellen Ordner gibt, der unserem Ziel entspricht.

Über Hinzufügen eines "Benutzerdefinierten Ordners" kann man dies jedoch erreichen. Folgende Daten müssen verwendet werden (der Name ist beliebig):

  • AlwaysCreate: false
  • Condition:
  • Default Location: [CommonAppDataFolder]
  • Property: COMMONAPPDATAFOLDER
  • Transitive: false

Sehr wichtig ist hierbei die Default Location Einstellung. Anschließend kann man einen eigenen Ordner unter diesen Ordner hinzufügen - dieser wird dann bei der Installation erstellt und steht somit zur Verfügung.

Microsoft hat ins Visual Studio bereits eine Möglichkeit integriert, dem System mitzuteilen, dass man von der UAC Bescheid weiß oder, dass man von ihr soviele Rechte wie möglich haben will.

2 | Erstellen von Manifestdateien

Auch wenn man hier schon zufrieden ist, sollte man auf jeden Fall zu jeder Applikation eine Manifestdatei hinzufügen. Ist man mit den Rechten des Benutzers auf jeden Fall zufrieden teilt man Windows damit nur mit, dass man von der UAC Bescheid weiß und ist auf jeden Fall Windows Vista und höher kompatibel. Benötigt man immer mehr Rechte oder will sein Programm nur durch Administratoren laufen lassen, so ist dies ein geschickter Weg ohne ein Token auszukommen.

Das Vorgehen zum Erstellen einer neuen Manifestdatei ist denkbar einfach. Im Ausgabeprojekt (nur Ausführbare Dateien haben eine Manifestdatei - Bibliotheken besitzen keine) fügt man ein neues Element hinzu und wählt als Typ "Anwendungsmanifestdatei". Anschließend geht man in die Projekteigenschaften und stellt die eben hinzugefügt Manifestdatei als Standardmanifestdatei ein. Möchte man Windows nur mitteilen, dass das erstellte Programm die UAC kennt, so endet dieser Abschnitt hier.

Ansonsten kann man jedoch noch mehr einstellen:

<!-- Der wichtigste Abschnitt -->
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- Diese Zeile sollte drin stehen wenn man mit den aktuellen Rechten immer zufrieden ist (Benutzer / Admin) -->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<!-- Diese Zeile sollte drin stehen wenn der Account Administratorrechte benötigt -->
<requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
<!-- Diese Zeile sollte drin stehen wenn der Benutzer alle möglichen Rechte verwenden sollte -->
<requestedExecutionLevel  level="highestAvailable" uiAccess="false" />
</requestedPrivileges>

Zwischen Codezeile #2 und #9 sollte also im Standardfall (jeder Benutzer ist willkommen) Codezeile #4 stehen. Will man nur Administratoren ins Programm lassen (mit Übergabe der vollen Administratorrechten an das Programm), so wählt man Codezeile #6. Könnten die vollen Rechte eines Standardbenutzers auch reichen, so wählt man Codezeile #8.

Was spricht nun dagegen immer Codezeile #8 zu verwenden? Das blöde daran ist, dass der Benutzer - falls er die UAC immer noch aktiviert hat (was der Fall ist von dem wir ausgehen) - bei jedem Programmstart die gelbe Box (bzw. blaue Box für signierte Codeschreiber) von Windows kriegt, welche ihn fragt ob er dem Programm wirklich die Rechte geben will. Dies ist sehr nervig und meistens unnötig.

Daher ist es häufiger geschickter (da es sich meistens nur um einige einzelne Aktionen handelt - welche nicht mal bei jeder Programmausführung getätigt werden müssen), explizit vor dem Ausführen der kritischen Aktion eine gelbe Box aufzumachen bzw. sich die benötigten Rechte zu holen. Dies verhindert, dass man den Benutzer sinnlos stört.

3 | Erhalten und Verwenden eines Tokens

Dieser Teil ist besonders für diejenigen interessiert, welche Registrierungsmanipulationen durchführen möchten.

To be continued.

Created . Last updated .

References

Sharing is caring!