I was trying to help a user out in a forum get a listing of all the SubKeys of a specific registry Key and thought I’d share my solution here.
Per the usual, there are a number of different ways to read the registry, but I found that using WMI is very simple.
To simplify things, I added the use of a ‘RegistryClass’ Enum so you don’t need to remember the various registry class constants.
Enough talk, here’s the code!
Enum RegistryClass
HKEY_CLASSES_ROOT = &H80000000
HKEY_CURRENT_USER = &H80000001
HKEY_LOCAL_MACHINE = &H80000002
HKEY_USERS = &H80000003
HKEY_CURRENT_CONFIG = &H80000005
End Enum
'---------------------------------------------------------------------------------------
' Procedure : WMI_EnumerateKeySubKeys
' Author : Daniel Pineault, CARDA Consultants Inc.
' Website : http://www.cardaconsultants.com
' Purpose : Enumerate all the subkeys in the specified registry key
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
' (CC BY-SA 4.0) - https://creativecommons.org/licenses/by-sa/4.0/
' Req'd Refs: Late Binding -> None required
' Early Binding -> Microsoft WMI Scripting VX.X Library
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sRegClass : The Registry Class that the parent key is in
' sParentKey: The Key to enumerate the subkeys of
'
' Usage:
' ~~~~~~
' Call WMI_EnumerateKeySubKeys(HKEY_CURRENT_USER, "Control Panel\International")
' Call WMI_EnumerateKeySubKeys(HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths")
'
' Revision History:
' Rev Date(yyyy-mm-dd) Description
' **************************************************************************************
' 1 2022-02-03 Initial Public Release
'---------------------------------------------------------------------------------------
Sub WMI_EnumerateKeySubKeys(ByVal sRegClass As RegistryClass, ByVal sParentKey As String)
'https://docs.microsoft.com/en-us/previous-versions/windows/desktop/regprov/enumkey-method-in-class-stdregprov
On Error GoTo Error_Handler
' #Const WMI_EarlyBind = False 'True => Early Binding / False => Late Binding
#If WMI_EarlyBind = True Then
Dim oWMI As WbemScripting.SWbemObject
#Else
Dim oWMI As Object
#End If
Dim aSubKeys As Variant
Dim sSubKey As Variant
Dim i As Long 'Sequential Counter
Set oWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
oWMI.EnumKey sRegClass, sParentKey, aSubKeys 'Get all the subkeys within the sParentKey
Debug.Print "No", "SubKey" 'Header
Debug.Print String(80, "-") 'Header
For Each sSubKey In aSubKeys 'Iterate through each subkey
i = i + 1
Debug.Print i, sSubKey
Next
Error_Handler_Exit:
On Error Resume Next
If Not oWMI Is Nothing Then Set oWMI = Nothing
Exit Sub
Error_Handler:
MsgBox "The following error has occured" & vbCrLf & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Source: WMI_EnumerateKeySubKeys" & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occured!"
Resume Error_Handler_Exit
End Sub
You can then use the procedure by simply doing:
Call WMI_EnumerateKeySubKeys(HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths")
which will return something along the lines of:
No SubKey -------------------------------------------------------------------------------- 1 7zFM.exe 2 brave.exe 3 cmmgr32.exe 4 dfshim.dll 5 excel.exe 6 firefox.exe 8 IEDIAG.EXE 9 IEDIAGCMD.EXE 10 IEXPLORE.EXE ...
Code Features
This code
- can be used as both Early or Late Binding, the choice is yours and set by changing the value of the WMI_EarlyBind constant.
- is bitness independent (works in both 32 and 64-bit installations)
- is application independent (should work in any VBA applications – Access, Excel, Outlook, PowerPoint, Word, …)

Hello Daniel,
Thank you for sharing this code, it looks just what I need, however, I get a type mismatch error 13 when i run the following command to list COM ports:
Call WMI_EnumerateKeySubKeys(HKEY_LOCAL_MACHINE, “HARDWARE\DEVICEMAP\SERIALCOMM”)
Not sure if this would reproduce on your set up. But I’m running this on:
Microsoft® Excel® for Microsoft 365 MSO (Version 2302 Build 16.0.16130.20754) 64-bit.
Thanks
Without knowing exactly what you’re trying to do, I suspect that you don’t really want to use oWMI.EnumKey, but rather oWMI.EnumKey. You can learn more about it at: https://learn.microsoft.com/en-us/previous-versions/windows/desktop/regprov/enumvalues-method-in-class-stdregprov.
Sub WMI_EnumerateKeyValues(ByVal sRegClass As RegistryClass, ByVal sParentKey As String)On Error GoTo Error_Handler
' #Const WMI_EarlyBind = False 'True => Early Binding / False => Late Binding
#If WMI_EarlyBind = True Then
Dim oWMI As WbemScripting.SWbemObject
#Else
Dim oWMI As Object
#End If
Dim aNames As Variant
Dim aTypes As Variant
Dim i As Long 'Sequential Counter
Set oWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
oWMI.EnumValues sRegClass, sParentKey, aNames, aTypes
Debug.Print "No", "Value", , "Type" 'Header
Debug.Print String(80, "-") 'Header
For i = 0 To UBound(aNames)
Debug.Print i + 1, aNames(i), aTypes(i)
Next
Error_Handler_Exit:
On Error Resume Next
If Not oWMI Is Nothing Then Set oWMI = Nothing
Exit Sub
Error_Handler:
MsgBox "The following error has occured" & vbCrLf & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Source: WMI_EnumerateKeyValues" & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occured!"
Resume Error_Handler_Exit
End Sub