Home » Tutorials » VCL » Einstieg in die Entwicklung für Windows Vista

Einstieg in die Entwicklung für Windows Vista

UAC: Dateisystemzugriffe

In Vista ist standardmäßig die strenge Benutzerkontrolle (UAC = User Account Controll) aktiviert. Selbst wenn man als Administrator angemeldet ist, wird man in bestimmten Fällen gefragt, ob man eine Aktion wirklich durchführen will. Während man unter Windows XP als Administrator noch ohne Probleme in das Verzeichnis C:Programme zugreifen konnte, ist das unter Vista nicht mehr so einfach möglich. Man muss zuerst zweimal bestätigen, dass man sich wirklich sicher ist.

Das bringt Probleme mit sich, insbesondere wenn man sich in seinen Programmen nicht darum gekümmert hat, wohin Dateien geschrieben werden. So ist es vielfach üblich, dass Einstellungsdateien (ini) direkt in das Verzeichnis der Anwendung geschrieben werden.

Virtualisierung

Solange man kein Vista-Manifest verwendet, funktioniert diese Anwendung trotzdem. Wie denn das, mag sich manch einer jetzt fragen. Haben alte Anwendungen etwa höhere Rechte? Nein, natürlich nicht. Vista trickst hier ein bisschen. Das Verzeichnis, auf das nicht zugegriffen werden darf (z.B. C:Programme) wird virtualisiert. Die Anwendung meint, sie würde nach C:Programme schreiben – in Wirklichkeit landet die Datei jedoch in einem „Virtual Store“ (z.B. C:UsersAppDataLocalVirtualStoreProgram Files). Wenn dies passiert ist, zeigt der Explorer einen Button „Kompatibilitätsdateien“ in der Toolbar an, wenn man C:Programme öffnet – somit hat man wenigstens eine Chance, die Dateien wieder zu finden.

Der Haken an der Sache: Der VirtualStore ist – wie am Pfad oben zu sehen ist – benutzerspezifisch. Wird die gleiche Anwendung von einem anderen Benutzer auf demselben System gestartet, so wird er die Datei nicht finden.

Wohin mit den Dateien?

Verwendet man das Vista-Manifest, um eine „Vista ready“-Applikation erstellen zu können, ist der Schreibzugriff auf C:Programme und andere Systemverzeichnisse nicht möglich. Jetzt stellt sich die Frage: Wohin dann mit den Dateien, die meine Anwendung schreiben will?
Diese Frage ist nicht ganz so einfach zu beantworten. Unter Windows gibt es viele vom System vorgegebene Stellen, die für solche Zwecke in Frage kommen. Grundlegend stellen sich zwei Fragen: Soll die Datei nur für den aktuell angemeldeten Benutzer sichtbar sein oder für alle Benutzer des Systems? Und soll der Anwender die Datei leicht im Explorer finden können, oder handelt es sich um eine Datei mit Programmeinstellungen, von der er gar nichts wissen muss?

Benutzerspezifische Verzeichnisse

  • Application Data (C:Users<Benutzer>AppDataRoaming)
  • Eigene Dateien (C:Users<Benutzer>Documents)

Jeder Benutzer des Systems hat unter seinem Konto einen eigenen Ordner von diesen beiden Varianten. Der AppData-Ordner ist standardmäßig versteckt. Hierhin wird sich also selten ein Benutzer per Explorer verirren. Das ist der ideale Ort für benutzerbezogene Einstellungsdaten.
Den Ordner „Eigene Dateien“ (bzw. „Dokumente“ unter Vista) ist jedem bekannt und sogar im Startmenü verlinkt. Das ist der Speicherort für Dateien, die der Benuter selbst bewusst erzeugt und anschließend vielleicht kopieren will.

Benutzerübergreifende Verzeichnisse

  • Common Application Data (C:ProgramData)
  • Gemeinsame Dateien (C:UsersPublicDocuments)

Diese beiden Ordner gibt es nur einmal pro System, sie sind unabhängig von Benutzerkonten. Zu beachten: Legt eine eigene Anwendung oder ein Setup einen Ordner unterhalb von ProgramData an, so ist dieser nur für den gerade aktiven Benutzer beschreibbar, auch wenn der Name „Common“ vielleicht etwas anderes suggeriert. D.h. direkt nach dem Anlegen sollten die Verzeichnisrechte so gesetzt werden, dass jeder Benuter die nötigen Rechte hat. Wird der Ordner während einer Installtion mit InnoSetup erzeugt, so geht das folgendermaßen:
[Dirs]
Name: „{commonappdata}FirmaAnwendung“; Permissions: everyone-full
Dadurch bekommt jeder Benutzer Vollzugriff auf den neuen Ordner. Und dass ist ja das Verhalten, das man von einem Ordner „Common AppData“ erwartet.
Die oben beispielhaft angegebenen Pfade gelten für Vista. Unter XP ist in der Regel „Users“ durch „Dokumente und Einstellungen“ zu ersetzen. Natürlich sollte man die Pfade nicht fest im Programm verwenden, sondern über ein API-Funktion ermitteln:

uses ShlObj, SysUtils;

function GetSpecialFolder(const AFolder: Integer): String;
var
  path: String
begin
  SetLength(path, 250);
  SHGetFolderPath(Application.Handle, AFolder, TOKEN_DEFAULTUSER, 0, PChar(path);
  result := PChar(path);
end;

Als Parameter können u.a. folgende Konstanten (definiert in der Unit ShlObj) verwendet werden:

  • CSIDL_APPDATA (z.B. C:Users<Benutzer>AppDataRoaming)
  • CSIDL_PERSONAL (z.B. C:Users<Benutzer>Documents)
  • CSIDL_COMMON_APPDATA (z.B. C:ProgramData)
  • CSIDL_COMMON_DOCUMENTS (z.B. C:UsersPublicDocuments)

Generell sollten Dateien natürlich nicht direkt in die genannten Ordner geschrieben werden, sondern in entsprechende Unterordner, die nach Firmen- und Anwendungsnamen benannt sind.

Systemverzeichnisse

Öffnet man als Anwender unter Windows Vista den Datei-Explorer, sieht man Ordner wie C:Programme, C:Benutzer usw.  Öffnet man hingegen eine Kommandozeile und lässt sich mit „dir“ die Verzeichnisse unter C: anzeigen, so bekommt man eine ganz andere Darstellung. Hier heißen die Ordner C:Program Files und C:Users. Was ist passiert? Der Windows-Explorer übersetzt die Ordnernamen zur Anzeige in die Sprache des Betriebssystems. Im Dateisystem heißt der Ordner aber in jedem Fall z.B. „Program Files“.
Wer bisher fest auf C:Programme zugegriffen hat, wird vielleicht Erfolg haben. Dennoch ist es sehr zu empfehlen, mit obiger Funktion den tatsächlichen Pfad eines Systemordners zu ermitteln (z.B. mit Parameter CSIDL_PROGRAM_FILES für das Programme-Verzeichnis).
Leider gibt es unter Windows keine API-Funktion, die einem aus „C:Program Files“ die lokalisierte Variante zur Anzeige in einer Anwendung macht oder umgekehrt. Andras Hausladen hat deswegen die beiden Funktionen PathGetPhysicalPath und PathGetLocalizedPath geschrieben, die in der Unit JclFileUtils.pas der JCL enthalten sind. Mehr Infos dazu in seinem Blog.