Registry per VBA, 32- und 64-Bit

Die Registry von Windows ist für den einen oder anderen ein Buch mit sieben Siegeln. Tatsache ist: Dort landen manche wichtigen Informationen, die Sie gegebenenfalls einmal mit VBA auslesen wollen, oder Sie wollen dafür sorgen, dass per VBA bestimmte Elemente in der Registry angelegt werden. Wir stellen einige Routinen vor, die Ihnen die Arbeit mit der Registry erleichtern. Gleichzeitig liefern wir den Code in 64-Bit-kompatibler Form.

Per VBA mit der Registry arbeiten

Wann und wo Sie auf eine Anforderung stoßen, die mit dem Lesen oder Schreiben von Registry-Werten per VBA zu tun hat, lassen wir einmal dahingestellt. Wichtig ist allein, dass Sie nach der Lektüre dieses Beitrags auf den Ernstfall vorbereitet sind!

Daher schauen wir uns in diesem Beitrag nicht nur einen Satz von Funktionen an, welche wiederum die API von Windows für den lesenden und schreibenden Zugriff auf die Registry nutzen, sondern liefern auch noch eine Reihe von Beispielen für die Anwendung dieser Funktionen.

Unser konkreter Anlass, uns mit dem Thema VBA-Zugriff auf die Registry auseinanderzusetzen, war der Beitrag Optionen per VBA für Access 2019 (www.access-im-unternehmen.de/1320). Hier haben wir untersucht, welche Einstellungen des Dialogs Access-Optionen in der Registry landen. Um schnell prüfen zu können, ob sich nach dem Ändern einer Option unter Access einer der Einträge in der Registry geändert hat, haben wir eine Tabelle erstellt, die alle bereits in der Registry vorhandenen Werte enthält. Diese Werte haben wir initial einmal aus dem entsprechenden Bereich der Registry ausgelesen.

Anschließend haben wir nach jeder Änderung eine Prozedur durchlaufen lassen, welche alle Werte der Registry mit den bestehenden Werten in der Tabelle abgeglichen und eventuelle Unterschiede oder gar neue Werte im Direktbereich ausgegeben hat.

Access-Einstellungen in der Registry

Den Bereich der Registry, der die Access-Optionen enthält, findet sich unter HKEY_CURRENT_USER im Ordner SOFTWARE\Microsoft\Office\16.0\Access\Settings. Der Screenshot aus Bild 1 zeigt einige der Einstellungen.

Dieser Bereich der Registry speichert die meisten der Access-Optionen.

Bild 1: Dieser Bereich der Registry speichert die meisten der Access-Optionen.

Auf diesen Ordner wollen wir uns in diesem Beitrag konzentrieren – wie lesen die Informationen aus, legen neue Werte an, erstellen Unterordner und so weiter. Vorher schauen wir uns allerdings noch die dazu notwendigen Funktionen im Modul mdlRegistry an.

Das Modul mdlRegistry und die Registry-Funktionen

Da das Modul die Deklaration von API-Funktion enthält sowie dafür vorgesehene Wrapperfunktionen, benötigen wir auch einige Enum– und Const-Elemente. Diese sehen wie folgt aus:

Public Enum Key
     HKEY_CLASSES_ROOT = &H80000000
     HKEY_CURRENT_USER = &H80000001
     HKEY_LOCAL_MACHINE = &H80000002
     HKEY_USERS = &H80000003
End Enum
Public Enum DataType
     dtString = 1
     dtNumber = 4
End Enum
Global Const ERROR_NONE = 0
Global Const ERROR_BADDB = 1
Global Const ERROR_BADKEY = 2
Global Const ERROR_CANTOPEN = 3
Global Const ERROR_CANTREAD = 4
Global Const ERROR_CANTWRITE = 5
Global Const ERROR_OUTOFMEMORY = 6
Global Const ERROR_INVALID_PARAMETER = 7
Global Const ERROR_ACCESS_DENIED = 8
Global Const ERROR_INVALID_PARAMETERS = 87
Global Const ERROR_NO_MORE_ITEMS = 259
Global Const KEY_ALL_ACCESS = &H3F
Global Const REG_OPTION_NON_VOLATILE = 0

Neben diesen Elementen benötigen wir die Deklarationen der eigentlichen API-Funktionen. Dabei handelt es sich um 13 Funktionen, deren Deklaration Sie in Listing 1 finden.

Declare PtrSafe Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
Declare PtrSafe 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, ByVal lpSecurityAttributes As Long, phkResult As Long, lpdwDisposition As Long) As Long
Declare PtrSafe 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
Declare PtrSafe Function RegQueryValueExString Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, _
     ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, ByVal lpData As String, lpcbData As Long) As Long
Declare PtrSafe Function RegQueryValueExLong Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, _
     ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, lpData As Long, lpcbData As Long) As Long
Declare PtrSafe Function RegQueryValueExNULL Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, _
     ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, ByVal lpData As Long, lpcbData As Long) As Long
Declare PtrSafe Function RegSetValueExString Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As Long, _
     ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, ByVal lpValue As String, _
     ByVal cbData As Long) As Long
Declare PtrSafe Function RegSetValueExLong Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As Long, _
     ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, lpValue As Long, ByVal cbData As Long) _
     As Long
Declare PtrSafe Function RegDeleteKey& Lib "advapi32.dll" Alias "RegDeleteKeyA" (ByVal hKey As Long, _
     ByVal lpSubKey As String)
Declare PtrSafe Function RegDeleteValue& Lib "advapi32.dll" Alias "RegDeleteValueA" (ByVal hKey As Long, _
     ByVal lpValueName As String)
Declare PtrSafe Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" (ByVal hKey As Long, _
     ByVal lpSubKey As String, phkResult As Long) As Long
Declare PtrSafe Function RegEnumKeyEx Lib "advapi32.dll" Alias "RegEnumKeyExA" (ByVal hKey As Long, _
     ByVal dwIndex As Long, ByVal lpName As String, lpcbName As Long, ByVal lpReserved As Long, _
     ByVal lpClass As String, lpcbClass As Long, lpftLastWriteTime As Any) As Long
Declare PtrSafe Function RegEnumValue Lib "advapi32.dll" Alias "RegEnumValueA" (ByVal hKey As Long, _
     ByVal dwIndex As Long, ByVal lpValueName As String, lpcbValueName As Long, ByVal lpReserved As Long, _
     lpType As Long, lpData As Byte, lpcbData As Long) As Long

Listing 1: Die benötigten API-Funktionen

Wrapperfunktion zum Auslesen von Werten

Die erste Wrapperfunktion soll das Auslesen eines Wertes für einen Eintrag eines Schlüssels/Unterschlüssels ermöglich. Diese Funktion erwartet drei Parameter:

  • lngKey: Einen der Werte der Enum-Auflistung Key, zum Beispiel HKEY_CURRENT_USER
  • strKeyName: Den Unterschlüssel, zum Beispiel SOFTWARE\Microsoft\Office\16.0\Access\Settings
  • strValueName: Den Namen des zu ermittelnden Elements, zum Beispiel Form Template

Die Funktion nutzt die API-Funktion RegOpenKeyEx, um den angegebenen Schlüssel zu öffnen. Dann liest sie mit RegQueryValueEx das gewünschte Element aus. Der Parameter varValue nimmt den gesuchten Wert auf.

Dieser wird in den folgenden Schritten noch untersucht und von nicht erwünschten Zeichen befreit. Schließlich wird dieser Wert zurückgegeben und der Registry-Schlüssel mit der API-Funktion RegCloseKey wieder geschlossen (siehe Listing 2)

Public Function QueryValue(lngKey As Key, strKeyName As String, strValueName As String)
     Dim lngRetVal As Long
     Dim hKey As Long
     Dim varValue As Variant
     lngRetVal = RegOpenKeyEx(lngKey, strKeyName, 0, KEY_ALL_ACCESS, hKey)
     lngRetVal = QueryValueEx(hKey, strValueName, varValue)
     varValue = Trim(varValue)
     If varValue <> "" Then
         If Asc(Right(varValue, 1)) > 127 Then
             varValue = Left(varValue, Len(varValue) - 1)
         End If
     End If
     If varValue <> "" Then
         If Asc(Right(varValue, 1)) < 21 Then
             varValue = Left(varValue, Len(varValue) - 1)
         End If
     End If
     QueryValue = varValue
     RegCloseKey hKey
End Function

Listing 2: Die Wrapperfunktion QueryValue

Wrapperfunktion zum Auslesen aller Einträge eines Schlüssels

Die Wrapperfunktion EnumKeyValues ermittelt alle Einträge der mit den Parametern übergebenen Schlüssel/Unterschlüssel-Kombination.

Die Funktion erwartet diese beiden Parameter:

  • lngKey: Einen der Werte der Enum-Auflistung Key, zum Beispiel HKEY_CURRENT_USER
  • strKeyName: Den Unterschlüssel, zum Beispiel SOFTWARE\Microsoft\Office\16.0\Access\Settings

Die Funktion öffnet wieder mit RegOpenKey den Schlüssel. Dann startet sie eine Do…Loop-Schleife, die dann endet, wenn die Funktion RegEnumValue den Wert 0 zurückgibt. Diese erhält in der Schleife wiederum einen Index als zweiten Parameter, der mit jedem Schleifendurchlauf erhöht wird, sowie als dritten Parameter eine mit 255 Leerzeichen vorbelegte Zeichenkette. Diese wird, sofern der aktuelle Index aus lngIndex ein gültiges Ergebnis hergibt, mit dem Namen des Eintrags gefüllt. Der Inhalt von strSave wird dann mit der Funktion StripTerminator von vbNullChar-Zeichen befreit und an das Array strKeys angehängt. Dieses gibt die Funktion schließlich als Ergebnis zurück:

Public Function EnumKeyValues(lngKey As Key, _
         strSubkey As String) As String()
     Dim hKey As Long
     Dim lngIndex As Long
     Dim strSave As String
     Dim strKeys() As String
     RegOpenKey lngKey, strSubkey, hKey
     Do
         strSave = String(255, 0)
         If RegEnumValue(hKey, lngIndex, strSave, 255, _
                 0, ByVal 0&, ByVal 0&, ByVal 0&) <> 0 Then
             Exit Do
         Else
             ReDim Preserve strKeys(lngIndex)
             strKeys(lngIndex) = StripTerminator(strSave)
             lngIndex = lngIndex + 1
         End If
     Loop
     RegCloseKey hKey
     EnumKeyValues = strKeys
End Function

Die Hilfsfunktion StripTerminator

Sie haben das Ende des frei verfügbaren Textes erreicht. Möchten Sie ...

TestzugangOder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar