Zurück zur Homepage

Zugriff auf die Registry

Um den Zugriff auf die Registry mittels API-Funktionen zu demonstrieren, habe ich mal eine kleine Klasse geschrieben, die den Zugriff kapselt. Ist nichts besonderes und erlaubt nur den Zugriff auf SZ Werte, die aber am häufigsten in der Registry vorkommen.
Schlüssel selbst können aber ohne Einschränkungen angelegt und gelöscht werden. Da es nicht funzt, Schlüssel zu löschen, die Unterschlüssel enthalten, werden vorher automatisch alle Unterschlüssel und deren Unterschlüssel ohne Rückfrage gelöscht.
Wie immer beim Arbeiten mit der Registry, muss äußerste Vorsicht gelten (Sicherheitskopie).
Jeder Fehler kann das System irepparabel schädigen
.
Ich hoffe ja, dass mein Code soweit fehlerfrei ist, nur garantieren tue ich nichts. Aber keine Panik, bei mir ist es fehlerfrei gelaufen.
Beim Anlegen von Schlüsseln werden bei meiner Klasse alle fehlenden Schlüssel automatisch angelegt, falls sie noch nicht vorhanden sind.
Wenn mehr Funktionen und andere Datentypen gebraucht werden, gibt es im Inet komplette Freeware- dll's, die den Zugriff auf die Registry auf einfache Art ermöglichen
Bei http://www.gssg.de/ unter VisualBasic findest man z.B. so etwas.

Beispielklasse (Registry.cls 12 KB)

 'Zur Demonstration in ein Modul

Sub SchlüsselAnlegen()
Dim a As New clsRegistry 'Neue Instanz der Klasse
a.Schlüssel = "Software\Microsoft\AAAAA\ABBBB\CCCCC\DDDDD\EEEEE"
a.SchlüsselAnlegen
End Sub


Sub SchlüsselLöschen()
Dim a As New clsRegistry 'Neue Instanz der Klasse
a.Schlüssel = "Software\Microsoft\AAAAA\ABBBB\CCCCC"
a.SchlüsselLöschen
End Sub


Sub WertAnlegen()
Dim a As New clsRegistry 'Neue Instanz der Klasse
a.Schlüssel = "SOFTWARE\Microsoft\AAAAA\ABBBB\Neuer Schlüssel #1"
a.SchlüsselAnlegen
'Schlüssel muss vorhanden sein
'a.Wertname = vbNullString 'Für den unbenannten Standardwert
a.Wertname = "Neuer Wert #3"
a.Wertinhalt = "1234567890"
End Sub


Sub WertAuslesen()
Dim a As New clsRegistry 'Neue Instanz der Klasse
'Schlüssel muss vorhanden sein
a.Schlüssel = "SOFTWARE\Microsoft\AAAAA\ABBBB\Neuer Schlüssel #1"
'a.Wertname = vbNullString 'Für den unbenannten Standardwert
a.Wertname = "Neuer Wert #3"
MsgBox a.Wertinhalt
End Sub


Sub WertLöschen()
Dim a As New clsRegistry 'Neue Instanz der Klasse
'Schlüssel muss vorhanden sein
a.Schlüssel = "SOFTWARE\Microsoft\AAAAA\ABBBB\Neuer Schlüssel #1"
a.Wertname = "Neuer Wert #3"
a.WertLöschen
End Sub

 

'##################################
'Und nun der Code der Klasse clsRegistry

Option Explicit
Private Declare 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


Private 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


Private Declare Function RegCloseKey Lib _
    "advapi32.dll" (ByVal hKey As Long) _
    As Long


Private Declare Function RegCreateKey Lib _
    "advapi32.dll" Alias "RegCreateKeyA" _
    (ByVal hKey As Long, _
    ByVal lpSubKey As String, _
    phkResult As Long) _
    As Long


Private Declare Function RegDeleteValue Lib _
    "advapi32.dll" Alias "RegDeleteValueA" _
    (ByVal hKey As Long, _
    ByVal lpValueName As String) _
    As Long


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


Private Declare Function RegSetValueEx Lib _
    "advapi32.dll" Alias "RegSetValueExA" _
    (ByVal hKey As Long, _
    ByVal lpValueName As String, _
    ByVal Reserved As Long, _
    ByVal dwType As Long, _
    lpData As Any, _
    ByVal cbData As Long) _
    As Long

Private Declare 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

Private Const STANDARD_RIGHTS_ALL = &H1F0000
Private Const SYNCHRONIZE = &H100000
Private Const REG_BINARY = 3
Private Const REG_SZ = 1
Private Const KEY_QUERY_VALUE = &H1
Private Const KEY_SET_VALUE = &H2
Private Const KEY_CREATE_SUB_KEY = &H4
Private Const KEY_NOTIFY = &H10
Private Const KEY_EVENT = &H1
Private Const KEY_ENUMERATE_SUB_KEYS = &H8
Private Const KEY_CREATE_LINK = &H20
Private Const KEY_ALL_ACCESS = _
    ((STANDARD_RIGHTS_ALL Or KEY_QUERY_VALUE _
    Or KEY_SET_VALUE Or KEY_CREATE_SUB_KEY _
    Or KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY _
    Or KEY_CREATE_LINK) And (Not SYNCHRONIZE))
Private Const HKEY_USERS = &H80000003
Private Const HKEY_CURRENT_USER = &H80000001
Private Const HKEY_LOCAL_MACHINE = &H80000002
Private Const ERROR_NO_MORE_ITEMS = 259&
Private myWert As String, myWertInhalt As String
Private myZweig As Long, mySchlüsselpfad As String
Private iWertBinary As Boolean


Private Sub iWertLesen()

Dim Zweig As Long, Schlüsselinhalt As String
Dim Länge As Long, dummy, Schlüsselhandle As Long, Typ&
    myWertInhalt = ""
    Zweig = getZweig()
    'Schlüssel öffnen, Handle holen
    dummy = RegOpenKeyEx(Zweig, mySchlüsselpfad, 0&, _
        KEY_QUERY_VALUE, Schlüsselhandle)
    If dummy <> 0 Then GoTo fehlerbehandlung
    'Länge ermitteln
    RegQueryValueExString Schlüsselhandle, myWert, 0&, _
        Typ, Schlüsselinhalt, Länge
    'Überprüfen, ob der Wert ein String ist
    If (Typ = REG_SZ) And (Länge > 0) Then
        'Puffer erzeugen
        Schlüsselinhalt = String(Länge, 0)
        'String holen
        RegQueryValueExString Schlüsselhandle, myWert, 0&, _
            Typ, Schlüsselinhalt, Länge
        myWertInhalt = Left(Schlüsselinhalt, Länge - 1)
    End If
fehlerbehandlung:
    RegCloseKey Schlüsselhandle
End Sub


Private Sub iWertSchreiben()

Dim Zweig As Long
Dim Länge As Long, dummy, Schlüsselhandle As Long, Typ&
    Zweig = getZweig()
    'Schlüssel öffnen, Handle holen
    dummy = RegOpenKeyEx(Zweig, mySchlüsselpfad, 0&, _
        KEY_ALL_ACCESS, Schlüsselhandle)
    'Überprüfen, ob der Wert ein String ist
    If dummy <> 0 Then GoTo fehlerbehandlung
    'String schreiben
    RegSetValueEx Schlüsselhandle, myWert, _
        0&, REG_SZ, ByVal myWertInhalt, Len(myWertInhalt)
fehlerbehandlung:
    RegCloseKey Schlüsselhandle
End Sub

Private Function iWertLöschen() As Boolean
Dim Zweig As Long, Schlüsselinhalt As String
Dim Länge As Long, dummy, Schlüsselhandle As Long, Typ&
    Zweig = getZweig()
    'Schlüssel öffnen, Handle holen
    dummy = RegOpenKeyEx(Zweig, mySchlüsselpfad, 0&, _
        KEY_ALL_ACCESS, Schlüsselhandle)
    If dummy = 0 Then 'Schlüssel ist vorhanden
        'Wert löschen
        dummy = RegDeleteValue(Schlüsselhandle, myWert)
        'Wenn Rückgabewert <>0, dann Fehler
        If dummy = 0 Then iWertLöschen = True
    End If
fehlerbehandlung:
    RegCloseKey Schlüsselhandle
End Function


Private Function iSchlüsselLöschenEx(Optional Hauptschlüssel As String)
Dim Zweig As Long, dummy, Schlüsselhandle As Long
Dim SName As String, Länge As Long
Dim actSchlüssel As String
Zweig = getZweig()
If Hauptschlüssel = "" Then Hauptschlüssel = mySchlüsselpfad
'Schlüssel öffnen, Handle holen
dummy = RegOpenKeyEx(Zweig, Hauptschlüssel, 0&, _
    KEY_ALL_ACCESS, Schlüsselhandle)
If dummy = 0 Then
    SName = String(255, 0) 'Puffer erzeugen
    Länge = Len(SName) 'Länge des Puffers
    'Ersten Unterschlüssel ermitteln
    dummy = RegEnumKeyEx(Schlüsselhandle, 0, SName, Länge, _
        ByVal 0&, vbNullString, ByVal 0&, ByVal 0&)
    Do 'Alle Unterschlüssel dieser Ebene durchlaufen
        'Keine Unterschlüssel da, Schleife verlassen

        If dummy = ERROR_NO_MORE_ITEMS Then Exit Do
        'Name des Unterschlüssels
        actSchlüssel = Left(SName, Länge)
        'Rekursiv aufrufen, um alle Unterschlüssel
        'dieses Schlüssels zu löschen

        iSchlüsselLöschenEx Hauptschlüssel & "\" & actSchlüssel
        'erst jetzt kann dieser Schlüssel gelöscht werden
        RegDeleteKey Schlüsselhandle, actSchlüssel
        SName = String(255, 0) 'Puffer erzeugen
        Länge = Len(SName) 'Länge des Puffers
        'Nächster Unterschlüssel, aber auch mit Index 0,
        'da vorher schon ein Schlüssel gelöscht wurde

        dummy = RegEnumKeyEx(Schlüsselhandle, 0, SName, Länge, _
            ByVal 0&, vbNullString, ByVal 0&, ByVal 0&)
    Loop
    'Handle schließen
    RegCloseKey Schlüsselhandle
    'Aus dem Pfad den eigentlich übergebenen Schlüssel holen
    actSchlüssel = GetUnterschlüssel(Hauptschlüssel)
    'Den übergeordneten Pfad des Schlüssels holen
    Hauptschlüssel = Left(Hauptschlüssel, _
        Len(Hauptschlüssel) - 1 - Len(actSchlüssel))
    'Schlüssel öffnen, Handle holen
    dummy = RegOpenKeyEx(Zweig, Hauptschlüssel, 0&, _
        KEY_ALL_ACCESS, Schlüsselhandle)
    'Jetzt wird der eigentlich übergebene Schlüssel gelöscht
    'Vorher wurden nur Unterschlüssel gelöscht

    If dummy = 0 Then RegDeleteKey Schlüsselhandle, actSchlüssel
End If
fehlerbehandlung:
    RegCloseKey Schlüsselhandle
End Function


Private Function iSchlüsselAnlegenEx() As Boolean
Dim Zweig As Long, dummy, Schlüsselhandle As Long, Typ&
Dim strSchlüssel As String, strSchlüsselVorher As String, arrSchlüssel, i As Long
    Zweig = getZweig()
    'Den Schlüsselpfad in Einzelschlüssel Splitten
    arrSchlüssel = SplitVBA(mySchlüsselpfad, "\")
    For i = 1 To UBound(arrSchlüssel)
        'Beginnend mit dem ersten Schlüssel aus dem
        'Array den Pfad aufbauen.

        strSchlüssel = strSchlüssel & arrSchlüssel(i)
        'Schlüssel öffnen, Handle holen
        dummy = RegOpenKeyEx(Zweig, strSchlüssel, 0&, _
            KEY_ALL_ACCESS, Schlüsselhandle)
        If dummy <> 0 Then 'Schlüssel fehlt, erst anlegen
            'Schlüssel öffnen, Handle holen
            dummy = RegOpenKeyEx(Zweig, strSchlüsselVorher, 0&, _
                KEY_ALL_ACCESS, Schlüsselhandle)
            'Schlüssel anlegen
            RegCreateKey Schlüsselhandle, arrSchlüssel(i), dummy
            If dummy <> 0 Then
                'Handle schließen
                RegCloseKey dummy
            Else
                'Schlüssel kann nicht angelegt werden
                GoTo fehlerbehandlung
            End If
        End If
        'Handle schließen
        RegCloseKey Schlüsselhandle
        strSchlüsselVorher = strSchlüssel
        strSchlüssel = strSchlüssel & "\"
    Next 'nächste Ebene
'Schlüssel wurde erfolgreich angelegt
iSchlüsselAnlegenEx = True
Exit Function
fehlerbehandlung:
    RegCloseKey Schlüsselhandle
End Function

Public Property Get Key_LocalMachine() As Boolean
    If myZweig = 0 Then Key_LocalMachine = True
    'Zweig ist HKEY_LOCAL_MACHINE
End Property


Public Property Let Key_LocalMachine(ByVal vNewValue As Boolean)
    If vNewValue Then myZweig = 0
    'Zweig ist HKEY_LOCAL_MACHINE
End Property


Public Property Get Key_CurrentUser() As Boolean

    If myZweig = 1 Then Key_CurrentUser = True
    'Zweig ist HKEY_CURRENT_USER
End Property


Public Property Let Key_CurrentUser(ByVal vNewValue As Boolean)

    If vNewValue Then myZweig = 1
    'Zweig ist HKEY_CURRENT_USER
End Property


Public Property Get Key_Users() As Boolean

    If myZweig = 2 Then Key_Users = True
    'Zweig ist HKEY_USERS
End Property


Public Property Let Key_Users(ByVal vNewValue As Boolean)

    If vNewValue Then myZweig = 2
    'Zweig ist HKEY_USERS
End Property

Public Property Get Wertinhalt() As String
    'Wertinhalt liefern
    iWertLesen
   Wertinhalt = myWertInhalt
End Property


Public Property Let Wertinhalt(ByVal vNewValue As String)

    'Wertinhalt setzen
    myWertInhalt = vNewValue
    iWertSchreiben
End Property


Public Property Get Schlüssel() As String

    'Pfad des Schlüssel
    Schlüssel = mySchlüsselpfad
End Property


Public Property Let Schlüssel(ByVal vNewValue As String)

    'Pfad des Schlüssel
    mySchlüsselpfad = vNewValue
End Property


Public Property Let Wertname(ByVal vNewValue As String)

    myWert = vNewValue
End Property


Public Property Get Wertname() As String

    Wertname = myWert
End Property


Public Function WertLöschen(Optional PfadZumWert As String) As Boolean

    If PfadZumWert <> "" Then
        myWert = GetUnterschlüssel(PfadZumWert)
        mySchlüsselpfad = Left(PfadZumWert, Len(PfadZumWert) - 1 - Len(myWert))
    End If
    WertLöschen = iWertLöschen()
End Function


Public Function SchlüsselAnlegen(Optional Schlüsselname As String) As Boolean

    If Schlüsselname <> "" Then
        myWert = vbNullString
        mySchlüsselpfad = Schlüsselname
    End If
    SchlüsselAnlegen = iSchlüsselAnlegenEx()
End Function


Public Function SchlüsselLöschen(Optional Schlüsselname As String) As Boolean

    If Schlüsselname <> "" Then
        myWert = vbNullString
        mySchlüsselpfad = Schlüsselname
    End If
    SchlüsselLöschen = iSchlüsselLöschenEx()
End Function


Private Function GetUnterschlüssel(Pfad)

Dim a As Long
Do
    If InStr(a + 1, Pfad, "\") Then _
        a = InStr(a + 1, Pfad, "\") _
        Else _
        Exit Do
Loop
GetUnterschlüssel = Right$(Pfad, Len(Pfad) - a)
End Function


Private Function SplitVBA(ByVal strText As String, Trenner As String)

Dim a As Long, b As Long, c()
Do
    b = InStr(1, strText, Trenner)
    ReDim Preserve c(1 To a + 1)
    If b = 0 Then c(a + 1) = strText: Exit Do
    c(a + 1) = Left$(strText, b - 1)
    strText = Right$(strText, Len(strText) - b)
    a = a + 1
Loop
SplitVBA = c
End Function


Private Function getZweig()

Select Case myZweig
    Case 0
        getZweig = HKEY_LOCAL_MACHINE
    Case 1
        getZweig = HKEY_CURRENT_USER
    Case 2
        getZweig = HKEY_USERS
End Select
End Function