API-Praxis: Zugriff auf die Registry

Wenn Sie ein Abonnement des Magazins 'Access im Unternehmen' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.

API-Praxis: Zugriff auf die Registry

Windows stellt einige API-Prozeduren zum Zugriff auf die Registry zur Verfügung. Die Registry verwaltet viele der für das System wichtigen Informationen. Hierzu gehören Informationen über das System, über die verschiedenen Anwendungen und Dateitypen und wie sie verknüpft werden und vieles mehr. Dieser Beitrag zeigt, wie Sie per VBA über die Funktionen der Windows-API auf die Registry zugreifen.

Neben den Informationen über das System finden Sie auch Informationen zu den Anwendungen selbst in der Registry. Wenn Sie zum Beispiel in den Optionen von Access den Standarddatenbankpfad ändern, wird der neue Pfad in die Registry eingetragen.

Auch wenn Sie der Datenbank einen neuen Assistenten oder ein Add-In hinzufügen, schreibt der Add-In-Manager die benötigten Informationen in die Registry. Für den Entwickler wird die Registry interessant, wenn er bestimmte Daten speichern will, die nicht in einer Tabelle untergebracht werden können oder sollen.

Die Registry ist im Prinzip wie das Dateisystem von Windows aufgebaut. Die Verzeichnisstruktur ist nahezu identisch. Statt der Dateien enthält die Registry Variablen. Wie die Dateien haben auch die Variablen einen bestimmten Inhalt.

Die Windows-API stellt einige Befehle zur Bearbeitung der Registry zur Verfügung. Im Folgenden lernen Sie Befehle, die Sie zum Hinzufügen, Bearbeiten und Entfernen von Schlüsseln benötigen, anhand eines Beispiels kennen.

Aufbau der Registry-Einträge

Die Einträge in die Registry, die Sie über den Befehl RegEdit öffnen (beispielsweise über das Suchen-Feld von Windows 10), sind nach einem bestimmten Schema aufgebaut. Auf der obersten Ebene befinden sich die Hauptpfade. Es gibt insgesamt fünf Hauptpfade, die Sie auch in Bild 1 sehen können:

Die Registry mit den fünf Hauptzweigen

Bild 1: Die Registry mit den fünf Hauptzweigen

  • HKEY_CLASSES_ROOT: Speichert Informationen über die unterschiedlichen Dateitypen und die dazugehörenden Anwendungen.
  • HKEY_CURRENT_USER: Speichert die Einstellungen des aktuellen Benutzers.
  • HKEY_LOCAL_MACHINE: Speichert Informationen über die Hard- und Software des Systems.
  • HKEY_USERS: Speichert die voreingestellten Einstellungen bezüglich Hard- und Software sowie benutzerdefinierte Änderungen.
  • HKEY_CURRENT_CONFIG: Speichert allgemeine Informationen über die Systemkonfiguration.

Jeder dieser Hauptpfade enthält weitere, aus unterschiedlich vielen Ebenen bestehende Unterpfade. Der unterste Pfad jeder der Ebenen enthält schließlich die eigentlichen Schlüssel. Die Schlüssel bestehen aus einem Namen und einem Wert. Mit dem Registrierungseditor, mit dem Sie die Einträge der Registry bequem einsehen, editieren und löschen sowie neue Einträge hinzufügen können, greifen Sie über die Benutzeroberfläche auf diese Schlüssel zu.

Der in Bild 2 markierte Pfad lautet beispielsweise HKEY_CURRENT_USERSOFTWAREMicrosoftOffice16.0AccessMenu Add-InsRibbonAdmin2016.

Die Access-Add-Ins und ihre Registrierung in der Windows-Registry

Bild 2: Die Access-Add-Ins und ihre Registrierung in der Windows-Registry

In dem Pfad finden Sie vier Schlüssel, die einige Informationen zu einem Access-Add-In beinhalten – unter anderem die Funktion, die beim Aufruf des Add-Ins gestartet werden soll, sowie der Ort der Bibliothek, in der die benötigte Funktion enthalten ist.

Praxisbeispiel: Shareware mit zeitlicher Begrenzung

Wenn Sie eine Datenbankanwendung als Shareware vertreiben, möchten Sie die Benutzung der Anwendung möglicherweise auf eine Testphase von beispielsweise 30 Tagen beschränken. Die Anwendung muss also bei jedem Start zunächst überprüfen, ob der angegebene Zeitraum schon beendet ist oder nicht. Dazu müssen Sie zunächst eine Information über das Installationsdatum oder das Datum der ersten Anwendung speichern.

Das Speichern der Daten innerhalb der Datenbank ist deshalb nicht zu empfehlen, weil der Anwender die Datenbank nach Ablauf der 30 Tage einfach neu installieren könnte. Eine weitere Möglichkeit ist das Speichern des Datums in der Registry. Wenn der Benutzer die Anwendung startet, vergleicht die Anwendung das in die Registry eingetragene Datum mit dem aktuellen Datum und soll den Benutzer gegebenenfalls auf das Ablaufen der Testphase hinweisen. Wenn der Benutzer dann die Datenbank neu installiert, findet die Datenbank den noch vorhandenen Registry-Eintrag und erkennt, dass die Testphase bereits einmal abgelaufen ist.

Zunächst einmal überlegt man sich, wo in der Registry ein solcher Wert am besten abgelegt wird. Da die Anwendung vermutlich unabhängig vom Benutzer auf dem Rechner installiert, wählt man den Hauptpfad HKEY_CURRENT_USER aus. Der Name des Pfades soll AMVShopBeispieleRegistry lauten. Den Schlüssel nennen Sie Installationsdatum und der Wert soll das aktuelle Datum sein.

Selbstverständlich sollten Sie die Informationen etwas besser verstecken und gegebenenfalls auch verschlüsseln, wenn Sie eine Anwendung wirksam schützen wollen. Da der vorliegende Anwendungsfall jedoch nur als Beispiel dienen soll, wird hier mit offenen Karten gespielt.

Konstanten

Im Rahmen der nachfolgend beschriebenen API-Funktionen definieren Sie einige Konstanten. Die Konstanten benötigen Sie, um innerhalb des VBA-Code statt nichtssagender Werte für den Entwickler verständliche Begriffe verwenden zu können. So definiert man beispielsweise die folgende Konstante HKEY_CLASSES_ROOT, um sie bei der Angabe eines Registryschlüssels statt des Ausdrucks &H80000003 zu verwenden:

Public Const HKEY_CLASSES_ROOT As Long = &H80000000

Damit Sie nicht zwischendurch immer wieder neue Kon­stanten definieren müssen, geben Sie direkt alle in Zusammenhang mit den Registryzugriffen benötigten Konstanten ein:

Public Const HKEY_CURRENT_USER   As Long = &H80000001
Public Const HKEY_LOCAL_MACHINE  As Long = &H80000002
Public Const HKEY_USERS          As Long = &H80000003
Public Const HKEY_CURRENT_CONFIG As Long = &H80000005
Public Const REG_STR             As Long = 1
Public Const REG_OPTION_NON_VOLATILE  As Long = 0
Public Const REG_SZ              As Long = 1
Public Const KEY_ALL_ACCESS      As Long = &H3F
Public Const StringlängeMax      As Long = 200
Public Const ERROR_SUCCESS       As Long = 0&
Public Const ERROR_NO_MORE_ITEMS As Long = 259&

Noch praktischer ist es, wenn Sie für die fünf Konstanten für die Hauptpfade der Registry gleich eine Enumeration anlegen. Dann können Sie später, wenn Sie in Funktionen eine dieser Konstanten als Parameter übergeben wollen, ganz einfach per Intellisense auf diese Konstanten zugreifen. Dies sieht dann so aus:

Public Enum eRegistryPfade
     HKEY_CLASSES_ROOT = &H80000000
     HKEY_CURRENT_USER = &H80000001
     HKEY_LOCAL_MACHINE = &H80000002
     HKEY_USERS = &H80000003
     HKEY_CURRENT_CONFIG = &H80000005
End Enum

Sie müssen die entsprechenden Konstanten dann allerdings löschen oder umbenennen, da sonst mehrere Elemente gleichen Namens im Code vorkommen, was zu Kompilierfehlern führt.

Achtung: Sie werden im Folgenden neben den Konstanten auch noch API-Funktionen deklarieren sowie VBA-Funktionen und -Prozeduren eingeben. Am besten legen Sie für die Konstanten und die API-Funktionen ein eigenes Modul an (zum Beispiel mdlAPIRegistry). Die VBA-Funktionen und -Prozeduren zum Thema Registry sollten Sie ebenso in einem eigenen Modul zusammenfassen – beispielsweise mdlRegistry.

Anlegen eines Schlüssels

Die API-Funktion RegCreateKeyEx dient zum Anlegen eines Registrierungsschlüssels. Falls der anzulegende Schlüssel bereits vorhanden ist, öffnet die Funktion den Schlüssel. Die Deklaration der Funktion lautet:

Declare Function RegCreateKeyEx _
     Lib "advapi32.dll" _
     Alias "RegCreateKeyExA" (_
     ByVal hKey As Long, _
     ByVal lpSubKey As String, _
     ByVal Reserved As Long, _
     ByVal lpClass As String, _
     ByVal dwOptions As Long, _
     ByVal samDesired As Long, _
     lpSecurityAttributes As SECURITY_ATTRIBUTES, _
     phkResult As Long, _
     lpdwDisposition As Long
) As Long

Interessant sind vor allem die Parameter hKey und lpSubKey. Für den Parameter hKey geben Sie entweder das Handle an, das auf den entsprechenden Eintrag in der Registry zeigt, oder Sie geben einen der Hauptpfade aus der obigen Liste ein. Für den Parameter lpSubKey geben Sie den Pfad des Registry-Wertes an, den Sie öffnen möchten.

Für den Parameter lpSecurityAttributes müssen Sie noch einen Type definieren, und zwar im Modul mdlAPIRegistry:

Private Type SECURITY_ATTRIBUTES
     nLength As Long
     lpSecurityDescriptor As Long
     bInheritHandle As Boolean
End Type

Um den Aufruf der API-Funktion ein wenig komfortabler zu gestalten, erstellen Sie eine Funktion, an die Sie einfach nur den Hauptpfad und den Pfad des Registry-Eintrages übergeben müssen:

Public Function SchluesselErstellen(lngHauptpfad As Long, _
         Pfad As String) As Long
...

Als Hauptpfad würden Sie nun eine der Konstanten wie etwa HKEY_LOCAL_MACHINE eingeben. Da wir dafür aber eine Enumeration angelegt haben, können Sie diese auch als Datentyp für lngHauptpfad angeben, sodass die Funktion nun wie in Listing 1 aussieht.

Public Function SchluesselErstellen(strHauptpfad As eRegistryPfade, strPfad As String) As Long
     Dim lngHandle As Long
     Dim secAttrib As SECURITY_ATTRIBUTES
     RegCreateKeyEx strHauptpfad, strPfad, 0&, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, secAttrib, lngHandle, 0&
     SchluesselErstellen = lngHandle
End Function

Listing 1: Hilfsfunktion zum Erstellen eines Schlüssels in der Registry

Sie können die Funktion zum Beispiel über das Testfenster aufrufen.

Geben Sie dort den folgenden Befehl ein, erhalten Sie Unterstützung bei der Auswahl des Hauptpfades (s. Bild 3):

Aufruf der Funktion SchluesselErstellen mit IntelliSense-Unterstützung

Bild 3: Aufruf der Funktion SchluesselErstellen mit IntelliSense-Unterstützung

MsgBox SchlüsselErstellen(HKEY_CURRENT_USER, "SOFTWAREHaufeBeispieleTest")

Das Meldungsfenster zeigt daraufhin die Nummer des Handles an, mit dem Sie auf den Eintrag in die Registry zugreifen können, ohne den kompletten Pfad eingeben zu müssen – zum Beispiel 4576.

Außerdem erstellt die Funktion den angegebenen Pfad in der Registry, wenn er nicht bereits vorhanden ist. Wenn der Pfad bereits erstellt wurde, bereitet die Funktion den Pfad auf den Zugriff vor. Mit dem Registrierungseditor können Sie schnell überprüfen, ob die Funktion den Registrierungsschlüssel wie gewünscht angelegt hat. Öffnen Sie den Editor und navigieren Sie zu dem entsprechenden Pfad (s. Bild 4).

Der neue Eintrag in der Windows-Registry

Bild 4: Der neue Eintrag in der Windows-Registry

Öffnen eines Schlüssels

Wenn Sie nur auf einen Schlüssel zugreifen möchten, verwenden Sie den API-Befehl RegOpenKey. Die Funktion hat die folgende Syntax:

Declare Function RegOpenKeyEx _
     Lib "advapi32.dll" _
     Alias "RegOpenKeyExA" ( _
     ByVal hKey As Long, _
     ByVal lpSubKey As String, _
     ByVal ulOptions As Long, _
     ByVal samDesired As Long, _
     phkResult As Long) _
As Long

Auch den Aufruf dieser API-Funktion können Sie ein wenig komfortabler gestalten, indem Sie eine Funktion erstellen, die nur die wichtigsten Werte als Parameter erfordert:

Die Funktion SchluesselOeffnen aus Listing 2 hat nur einen Unterschied im Vergleich zu der vorherigen Funktion: Sie erstellt keinen neuen Schlüssel, falls der angegebene Schlüssel nicht vorhanden ist. Beachten Sie, dass die API-Funktion keinen Fehler auslöst, wenn der zu öffnende Schlüssel nicht vorhanden ist. Sie gibt lediglich für das Handle den Wert 0 zurück.

Public Function SchluesselOeffnen(lngHauptpfad As eRegistryPfade, strPfad As String) As Long
     Dim lngHandle As Long
     RegOpenKeyEx lngHauptpfad, strPfad, 0, KEY_ALL_ACCESS, lngHandle
     SchluesselOeffnen = lngHandle
End Function

Listing 2: Hilfsfunktion zum Ermitteln des Handles eines Registry-Eintrags

Ein Beispielaufruf sieht wie folgt aus:

  SchluesselOeffnen(HKEY_CURRENT_USER, "SOFTWAREAMVShopBeispieleTest")
  3816 

Entfernen eines Schlüssels

Bevor Sie beginnen, den neuen Schlüssel mit Werten zu füllen, erfahren Sie noch, wie Sie einen Schlüssel per API-Aufruf wieder entfernen können. Auch das ist wichtig, denn wenn Sie mit der Installation der Software in die Registry eingreifen, sollten Sie die Änderung bei einer Deinstallation auch wieder rückgängig machen. Zum Löschen eines Pfades in der Registry verwendet man den API-Befehl RegDeleteKey, den Sie wie folgt deklarieren:

Declare Function RegDeleteKey _
     Lib "advapi32.dll" _
     Alias "RegDeleteKeyA" ( _
     ByVal hKey As Long, _
     ByVal lpSubKey As String _
) As Long

Die Funktion erwartet nur den Hauptpfad und den Pfad des zu löschenden Schlüssels. Die Funktion gibt den Wert 0 zurück – es sei denn, die Operation schlägt fehl, zum Beispiel, weil der angegebene Pfad nicht vorhanden ist. Wichtig ist, dass Sie den kompletten zu entfernenden Pfad bis in die unterste Ebene angeben.

Auch für diese API-Funktion haben wir wieder eine Wrapper-Funktion programmiert, die Sie in Listing 3 finden.

Public Function SchluesselLoeschen(lngHauptpfad As eRegistryPfade, strPfad As String) As Long
     Dim lngHandle As Long
     lngHandle = RegDeleteKey(lngHauptpfad, strPfad)
     SchluesselLoeschen = lngHandle
End Function

Listing 3: Hilfsfunktion zum Löschen eines Eintrags

Wenn Sie nun den gleichen Pfad wieder löschen wollen, den Sie soeben angelegt haben, gelingt dies nicht mit dem folgenden Aufruf der Funktion:

  SchluesselLoeschen(HKEY_CURRENT_USER, "SOFTWAREAMVShopBeispieleTest")
0

Dies liefert mit dem Wert 0 zwar eine Erfolgsmeldung, allerdings wird hier logischerweise nur genau das angegebene Element gelöscht, nämlich das Verzeichnis Test.

Wenn Sie alle Verzeichnisse löschen wollen, die Sie zuvor angelegt haben, sind noch zwei weitere Aufrufe nötig – Sie müssen nämlich jedes Verzeichnis vom hintersten an einzeln löschen:

Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.

Bitte geben Sie die Zeichenfolge in das nachfolgende Textfeld ein

Die mit einem * markierten Felder sind Pflichtfelder.

Ich habe die Datenschutzbestimmungen zur Kenntnis genommen.