Link to home
Start Free TrialLog in
Avatar of jmnolan
jmnolan

asked on

RegDeleteKey

The documentation says:

Windows 95: The RegDeleteKey function deletes a key and all its descendents.

Windows NT: The RegDeleteKey function deletes the specified key. This function cannot delete a key that has subkeys.

My Question:
How do I delete a key and all subkeys in Windows NT. I was trying to use RegOpenKey and recursively go through the keys but I figured someone might have done this already. Anyone?
Avatar of EDDYKT
EDDYKT
Flag of Canada image

Avatar of jmnolan
jmnolan

ASKER

Where is the function that deletes all of the subkeys of a specified key?
I didn't write this, it comes from MSDN.  I use it for both Win9x and WinNT and it works fine.  Just copy this code into a module and call the procedures to edit the registry:

Global Const REG_SZ As Long = 1
Global Const REG_DWORD As Long = 4
 
Global Const HKEY_CLASSES_ROOT = &H80000000
Global Const HKEY_CURRENT_USER = &H80000001
Global Const HKEY_LOCAL_MACHINE = &H80000002
Global Const HKEY_USERS = &H80000003
 
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
 
Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
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, ByVal lpSecurityAttributes As Long, phkResult As Long, lpdwDisposition As Long) As Long
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
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
Declare 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 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 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 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
 

Public Sub CreateNewKey(sNewKeyName As String, lPredefinedKey As Long)

    'With this procedure a call of
    '     CreateNewKey "TestKey", HKEY_CURRENT_USER
    ' will create a key called TestKey immediately under HKEY_CURRENT_USER.
   
    ' Calling CreateNewKey Like this
 
    '      CreateNewKey "TestKey\SubKey1\SubKey2", HKEY_LOCAL_MACHINE
 
    ' will create a three-nested keys beginning with TestKey immediately under
    ' HKEY_CURRENT_USER, SubKey1 subordinate to TestKey, and SubKey3 under
    ' SubKey2.
       
       
       
    Dim hNewKey As Long         'handle to the new key
    Dim lRetVal As Long         'result of the RegCreateKeyEx function
 
    lRetVal = RegCreateKeyEx(lPredefinedKey, sNewKeyName, 0&, vbNullString, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0&, hNewKey, lRetVal)
    RegCloseKey (hNewKey)

End Sub
Public Function QueryValue(lKey As Long, sKeyName As String, sValueName As String) As Variant
   
    ' With this procedure, a call of
    '    QueryValue "TestKey\SubKey1", "StringValue"
 
    ' will display a message box with the current setting of the "StringValue"
    ' value, and assumes that "StringValue" exists in the "TestKey\SubKey1" key.
 
    ' If the Value that you query does not exist then QueryValue will return an
    ' error code of 2 - 'ERROR_BADKEY'.

       
    Dim lRetVal As Long         'result of the API functions
    Dim hKey As Long         'handle of opened key
    Dim vValue As Variant      'setting of queried value
    lRetVal = RegOpenKeyEx(lKey, sKeyName, 0, KEY_ALL_ACCESS, hKey)
    lRetVal = QueryValueEx(hKey, sValueName, vValue)
    If vValue <> "" Then
        If InStr(vValue, Chr$(0)) Then
            QueryValue = Left$(vValue, InStr(vValue, Chr$(0)) - 1)
        Else
            QueryValue = vValue
        End If
    End If
    RegCloseKey (hKey)
End Function

Public Sub SetKeyValue(lKey As Long, sKeyName As String, sValueName As String, vValueSetting As Variant, lValueType As Long)
   
    ' A call of
    '   SetKeyValue "TestKey\SubKey1", "StringValue", "Hello", REG_SZ
 
    ' will create a value of type REG_SZ called "SubKey1" with the setting of
    ' "Hello". This value will be associated with the key SubKey1 of "TestKey".
 
    ' if the value is not found it will create it
    ' In this case, "TestKey" is a subkey of HKEY_CURRENT_USER, but this can be
    ' modified by changing the call to RegOpenKeyEx. This call will fail if
    ' "TestKey\SubKey1" does not exist. To avoid this problem, use a call to
    ' RegCreateKeyEx instead of a call to RegOpenKeyEx. RegCreateKeyEx will open
    ' a specified key if it already exists.

    Dim lRetVal As Long         'result of the SetValueEx function
    Dim hKey As Long         'handle of open key
   
    'open the specified key
    lRetVal = RegOpenKeyEx(lKey, sKeyName, 0, KEY_ALL_ACCESS, hKey)
    If ERROR_BADKEY Then
        ' Create the key
        CreateNewKey sKeyName, lKey
        lRetVal = RegOpenKeyEx(lKey, sKeyName, 0, KEY_ALL_ACCESS, hKey)
    End If
       
    lRetVal = SetValueEx(hKey, sValueName, lValueType, vValueSetting)
    RegCloseKey (hKey)
End Sub

Public Function SetValueEx(ByVal hKey As Long, sValueName As String, lType As Long, vValue As Variant) As Long
    Dim lValue As Long
    Dim sValue As String
    Select Case lType
        Case REG_SZ
            sValue = vValue
            SetValueEx = RegSetValueExString(hKey, sValueName, 0&, lType, sValue, Len(sValue))
        Case REG_DWORD
            lValue = vValue
            SetValueEx = RegSetValueExLong(hKey, sValueName, 0&, lType, lValue, 4)
        End Select
End Function
 
Function QueryValueEx(ByVal lhKey As Long, ByVal szValueName As String, vValue As Variant) As Long
    Dim cch As Long
    Dim lrc As Long
    Dim lType As Long
    Dim lValue As Long
    Dim sValue As String
 
    On Error GoTo QueryValueExError
 
    ' Determine the size and type of data to be read
    lrc = RegQueryValueExNULL(lhKey, szValueName, 0&, lType, 0&, cch)
    'If lrc <> ERROR_NONE Then Error 5
 
    Select Case lType
        ' For strings
        Case REG_SZ:
            sValue = String(cch, 0)
            lrc = RegQueryValueExString(lhKey, szValueName, 0&, lType, sValue, cch)
            If lrc = ERROR_NONE Then
                vValue = Left$(sValue, cch)
            Else
                vValue = Empty
            End If
        ' For DWORDS
        Case REG_DWORD:
            lrc = RegQueryValueExLong(lhKey, szValueName, 0&, lType, lValue, cch)
            If lrc = ERROR_NONE Then vValue = lValue
        Case Else
            'all other data types not supported
            lrc = -1
    End Select
 
QueryValueExExit:
    QueryValueEx = lrc
    Exit Function
QueryValueExError:
    Resume QueryValueExExit
End Function



Avatar of jmnolan

ASKER

I still don't see a function that deletes all of the subkeys of a specified key. I am not looking to edit registry entries or look at their value. I want to be able to delete a key and all subkeys of that key.
Sorry about that I didn't realize there wasn't a delete in it and I had 'assumed' I had used it for deleting registry keys.  I believe I have a solution to your problem however.  The only that I have found to delete the key and any subkeys is with a recursive function, I wrote the following function and it works great:

Copy this to a module:

Option Explicit

Public 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
Public Declare Function RegDeleteKey Lib "advapi32.dll" Alias "RegDeleteKeyA" (ByVal hKey As Long, ByVal lpSubKey As String) As Long
Public Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long

Public Const STANDARD_RIGHTS_ALL = &H1F0000
Public Const KEY_QUERY_VALUE = &H1
Public Const KEY_SET_VALUE = &H2
Public Const KEY_CREATE_SUB_KEY = &H4
Public Const KEY_ENUMERATE_SUB_KEYS = &H8
Public Const KEY_NOTIFY = &H10
Public Const KEY_CREATE_LINK = &H20
Public Const SYNCHRONIZE = &H100000
Public Const ERROR_SUCCESS = 0&
Global Const HKEY_CLASSES_ROOT = &H80000000
Global Const HKEY_CURRENT_USER = &H80000001
Global Const HKEY_LOCAL_MACHINE = &H80000002
Public 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))

Public Function RegDeleteKeyNT(hKey As Long, StartKey As String, EndKey As String) As Long
   
    ' Local Variable Declarations:
    Dim dwReturn As Long
    Dim hReturnKey As Long
    Dim strKeyToDelete As String
    Dim intPosition As Integer
    Dim lngReturnCode As Long
   
    ' Assign parameter value to local variable:
    strKeyToDelete = StartKey
   
    ' Open the key:
    If RegOpenKeyEx(hKey, strKeyToDelete, 0, KEY_ALL_ACCESS, hReturnKey) = ERROR_SUCCESS Then
       
        ' If open was successful then itterate through keys until the key length is less
        ' than the length of the end key:
        Do While Len(strKeyToDelete) > Len(EndKey)
            If (dwReturn = RegDeleteKey(hKey, strKeyToDelete)) = ERROR_SUCCESS Then
               
                ' If the delete was successful then find the first '\' in reverse:
                intPosition = InStrRev(strKeyToDelete, "\", , vbTextCompare)
               
                ' Trim the string and assign the value to our local variable:
                strKeyToDelete = Left(strKeyToDelete, intPosition - 1)
            End If
           
        Loop
       
    End If
   
    ' Close the key:
    RegCloseKey (hKey)
   
End Function

Now I just added some keys under HKEY_LOCAL_MACHINE\SOFTWARE, one is Test, second is TestKey1, third is TestKey2 and forth is OK.  Here is how the function looks when it is called from a command button click event:

Private Sub Command1_Click()
    RegDeleteKeyNT HKEY_LOCAL_MACHINE, "SOFTWARE\TEST\TESTKEY1\TESTKEY2\OK", "\SOFTWARE\"
End Sub


The first parameter is the root key of course, the second parameter is the 'deepest' key you want to delete, and finally the last parameter is the key you want it to stop at (it will not be deleted).  I have tried this out with several different registry entries and it works fine.

Let me know if this is what you needed!!!



Avatar of jmnolan

ASKER

That seems closer but it still isn't right. I want to pass one key and have all of the subkeys deleted for that key. Your function will only work if there are no other children in the tree on the way back up.

I also forgot to mention that I am using VB5 so there is no InStrRev function.

If someone can supply me with a way to get all of the subkeys of a key in some sort of array I should be able to write the recursive delete function myself.
Have you looked at the sample program that comes with VB called 'vbreg.vbp'.  It may have what you are looking for.  If you don't have this sample let me know and I can zip it and e-mail it to you.
Avatar of jmnolan

ASKER

Is that VB6? I've got VB5 Ent, there is no vbreg.vbp project. If it has something that can do what I want then send it to me. Thanks.

jmnolan@neddam.com
ASKER CERTIFIED SOLUTION
Avatar of FlorisMK
FlorisMK
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of jmnolan

ASKER

Bingo FlorisMK. That's the function I was looking for.

THANKS!!!

There is another easy way to delete all key and its sub key.


There are regtool5.dll that come with VB6 (if you are using vb6)

Add Registry access function into your references

Option Explicit

Private Sub Command1_Click()
Dim regist As New Registry

Debug.Print regist.DeleteKey(HKEY_LOCAL_MACHINE, "software\inco")
End Sub

Add the sub key under HKEY_LOCAL_MACHINE\software\inco will be deleted
And THANK YOU, EDDYKT!!!! I didn't know about that one, and it makes simple Registry access so much easier!!!