Iterate through Registry Subfolders - vbscript

I want to get all values of a registry path include the values of its subfolders. Right now i read the values of a single folder by this:
const HKEY_LOCAL_MACHINE = &H80000002
strComputer = "."
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" &_
strComputer & "\root\default:StdRegProv")
strKeyPath = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
oReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys
For Each subkey In arrSubKeys
msgbox subkey ' Just for debugging
Next
This works great, but in addition i need to get a list of the folder's subfolders.
I want to get a result (only the content is important, not the formatting and no need to write it into a file) like the this would command gives me:
regedit /e c:\testfile.reg
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
Is there a way to do this in vbs or do i need to use the regedit command from windows, with an Wscript.Shell call.

You need to recurse into the subkeys. Try this:
Const HKEY_LOCAL_MACHINE = &H80000002
strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
Sub EnumerateKeys(hive, key)
WScript.Echo key
reg.EnumKey hive, key, arrSubKeys
If Not IsNull(arrSubKeys) Then
For Each subkey In arrSubKeys
EnumerateKeys hive, key & "\" & subkey
Next
End If
End Sub
Set reg = GetObject("winmgmts://./root/default:StdRegProv")
EnumerateKeys HKEY_LOCAL_MACHINE, strKeyPath

In addition i found a realy good example on the web:
' Constants (taken from WinReg.h)
'
Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS = &H80000003
Const REG_SZ = 1
Const REG_EXPAND_SZ = 2
Const REG_BINARY = 3
Const REG_DWORD = 4
Const REG_MULTI_SZ = 7
' Chose computer name, registry tree and key path
'
strComputer = "." ' Use . for current machine
hDefKey = HKEY_LOCAL_MACHINE
strKeyPath = "SOFTWARE\Microsoft\Cryptography\Defaults\Provider"
' Connect to registry provider on target machine with current user
'
Set oReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
' Enum the subkeys of the key path we've chosen
'
oReg.EnumKey hDefKey, strKeyPath, arrSubKeys
For Each strSubkey In arrSubKeys
' Show the subkey
'
wscript.echo strSubkey
' Show its value names and types
'
strSubKeyPath = strKeyPath & "\" & strSubkey
oReg.EnumValues hDefKey, strSubKeyPath, arrValueNames, arrTypes
For i = LBound(arrValueNames) To UBound(arrValueNames)
strValueName = arrValueNames(i)
Select Case arrTypes(i)
' Show a REG_SZ value
'
Case REG_SZ
oReg.GetStringValue hDefKey, strSubKeyPath, strValueName, strValue
wscript.echo " " & strValueName & " (REG_SZ) = " & strValue
' Show a REG_EXPAND_SZ value
'
Case REG_EXPAND_SZ
oReg.GetExpandedStringValue hDefKey, strSubKeyPath, strValueName, strValue
wscript.echo " " & strValueName & " (REG_EXPAND_SZ) = " & strValue
' Show a REG_BINARY value
'
Case REG_BINARY
oReg.GetBinaryValue hDefKey, strSubKeyPath, strValueName, arrBytes
strBytes = ""
For Each uByte in arrBytes
strBytes = strBytes & Hex(uByte) & " "
Next
wscript.echo " " & strValueName & " (REG_BINARY) = " & strBytes
' Show a REG_DWORD value
'
Case REG_DWORD
oReg.GetDWORDValue hDefKey, strSubKeyPath, strValueName, uValue
wscript.echo " " & strValueName & " (REG_DWORD) = " & CStr(uValue)
' Show a REG_MULTI_SZ value
'
Case REG_MULTI_SZ
oReg.GetMultiStringValue hDefKey, strSubKeyPath, strValueName, arrValues
wscript.echo " " & strValueName & " (REG_MULTI_SZ) ="
For Each strValue in arrValues
wscript.echo " " & strValue
Next
End Select
Next
Next

Related

Unable to read uninstall keys for x64 registry, vbscript

I was trying to read the Uninstall Keys (DisplayName, Display Version, Vendor ..) from both 32 and 64 Bit installation keys. I have below code but it is always giving only 32 bit keys info. As I wrote the below code it is giving the entries from 32 bit twice :(
' Constants (taken from WinReg.h)
'
Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS = &H80000003
Const REG_SZ = 1
Const REG_EXPAND_SZ = 2
Const REG_BINARY = 3
Const REG_DWORD = 4
Const REG_MULTI_SZ = 7
' Chose computer name, registry tree and key path
'
Set objExcel = CreateObject("Excel.Application")
objExcel.Workbooks.Add
ObjExcel.Cells (1,1) = "Application Name"
ObjExcel.Cells (1,4) = "Application Vendor"
ObjExcel.Cells (1,2) = "Application Version"
ObjExcel.Cells (1,3) = "DRM Build"
strComputer = InputBox("Enter the Machine name. To run on the current machine, press ENTER", "Machine Name", "")
If strComputer = "" Then
strComputer = "."
End If
Msgbox "Script is Running and may take couple of minutes to complete. Click on OK to continue",0, "Information"
hDefKey = HKEY_LOCAL_MACHINE
' Connect to registry provider on target machine with current user
Set oReg = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")
'{impersonationLevel=impersonate}!
' Enum the subkeys of the key path we've chosen
strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
row = 2
getRegistryEntries hDefKey, strKeyPath, ObjExcel, oReg, row
strKeyPath = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
getRegistryEntries hDefKey, strKeyPath, ObjExcel, oReg, row
fileName = Year(now) & month(now) & day(now) & hour(now) & minute(now) & second(now)
ObjExcel.ActiveWorkbook.SaveAs "C:\" & fileName & ".xlsx"
ObjExcel.Quit
Set ObjExcel = Nothing
msgbox "Work Done, file saved in C Drive with the name: " & fileName
Function getRegistryEntries(hDefKey, strKeyPath, byRef objExcel, byRef oReg, byRef row)
oReg.EnumKey hDefKey, strKeyPath, arrSubKeys
Set objShell = CreateObject("WScript.Shell")
For Each strSubkey In arrSubKeys
' Show the subkey
'
furtherKeys = False
strDisName = "HKEY_LOCAL_MACHINE\" & strKeyPath & "\" & strSubkey & "\DisplayName"
On Error Resume Next
present = False
disName = objShell.RegRead(strDisName)
If disName <> "" Then
present = True
End If
disVersionPresent = false
disVer = ""
If present = true Then
strDisVer = "HKEY_LOCAL_MACHINE\" & strKeyPath & "\" & strSubkey & "\DisplayVersion"
strDisVendor = "HKEY_LOCAL_MACHINE\" & strKeyPath & "\" & strSubkey & "\Publisher"
strDRMBuild = "HKEY_LOCAL_MACHINE\" & strKeyPath & "\" & strSubkey & "\DRMBUILD"
disVer = objShell.RegRead(strDisVer)
If err.number = 0 Then
disVersionPresent = True
End If
If disVersionPresent Then
ObjExcel.Cells (row,1) = disName
ObjExcel.Cells (row,2) = "'" & disVer
furtherKeys = True
disVendor = objShell.RegRead(strDisVendor)
If err.number = 0 Then
ObjExcel.Cells (row,4) = disVendor
End If
DRMBuild = objShell.RegRead(strDRMBuild)
If err.number = 0 Then
ObjExcel.Cells (row,3) = "'" & DRMBuild
End If
End If
End If
If furtherKeys Then
row = row + 1
End If
Next
End Function

How to retrieve everything below a given registry key?

I have one script retrieve all registry values in a specific key (Ex: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET), but I need consult in making that search recursive. I need print all registry and subkeys below this key (Ex: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET)
Example for my script:
For Each strSubkey In arrSubKeys
Set objHtml=fso.Opentextfile(strComputer & ".txt",intForWriting,Createfile)
strValue = Null
strSubKeyPath = pathKeyReg & "\" & strSubkey
objRegistry.EnumValues hDefKey, strSubKeyPath, arrValueNames, arrTypes
For i = LBound(arrValueNames) To UBound(arrValueNames)
strValueName = arrValueNames(i)
Select Case arrTypes(i)
Case REG_SZ
objRegistry.GetStringValue hDefKey, strSubKeyPath, strValueName, strValue
objHtml.WriteLine strSubKeyPath & vbTab & strValueName & vbTab & "(REG_SZ)" & vbTab & strValue
' Show a REG_EXPAND_SZ value
Case REG_EXPAND_SZ
objRegistry.GetExpandedStringValue hDefKey, strSubKeyPath, strValueName, strValue
objHtml.Write strSubKeyPath & vbTab & strValueName & vbTab & "(REG_EXPAND_SZ)" & vbTab & strValue
End Select
Next
Next
You need to recurse into subkeys for that. Wrap your code in a procedure and add code that enumerates the subkeys of the current key and calls itself for each subkey.
Sub RecurseKey(key)
'enumerate values (your existing code)
objRegistry.EnumValues hDefKey, key, names, types
If Not IsNull(names) Then
For i = 0 To UBound(names)
name = names(i)
Select Case types(i)
Case REG_SZ
...
Case REG_EXPAND_SZ
...
Case ...
End Select
Next
End If
'enumerate subkeys and recurse
objRegistry.EnumKey hDefKey, key, subKeys
If Not IsNull(subKeys) Then
For Each sk In subKeys
RecurseKey key & "\" & sk '<-- recursion happens here
Next
End If
End Sub

How to delete array of registry keys and their subkeys

I am trying to delete array of registry keys and their subkeys.
Following is my code
Function DeleteSubkeys(strKeyPath)
Msgbox"DeleteSubkeys starts "
Dim strComputer,arrSubkeys
Const HKEY_LOCAL_MACHINE = &H80000002
strComputer = "."
Set objRegistry = GetObject("winmgmts:\\" & _
strComputer & "\root\default:StdRegProv")
objRegistry.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubkeys
If IsArray(arrSubkeys) Then
For Each strSubkey In arrSubkeys
DeleteSubkeys HKEY_LOCAL_MACHINE, strKeyPath & "\" & strSubkey
Next
End If
objRegistry.DeleteKey HKEY_LOCAL_MACHINE, strKeyPath
Msgbox"DeleteSubkeys ends "
DeleteSubkeys= null
End Function
Msgbox"Main starts "
dim Regkey
Regkey = Array(_
"SOFTWARE\Wow6432Node\Myproj\test1",_
"SOFTWARE\Wow6432Node\Myproj\test2"_
)
Msgbox"Outside foreach "
For Each strRegKey IN Regkey
Msgbox"Inside foreach "
DeleteSubkeys strRegKey
Next
Msgbox"Main ends "
But it fails to call function DeleteSubKeys which is invoked inside forach. What am i missing here?

Recursive search of HKU registry hive for a DWORD value

I need help with a VBScript that will recursively search the Windows HKU registry hive for a DWORD value. It would be helpful if the script could ignore the system accounts only looking in the S-1-5-21* keys. I MUST accomplish this using the HKU hive and not the HKCU hive because the program I plan to use to run the script runs in the context of system. No way around that.
Thank you.
Const HKCU = &H80000001
Const HKLM = &H80000002
Const HKU = &H80000003
strComputer = "."
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\default:StdRegProv")
'Read the HKEY_CURRENT_USER hive, registry path, and valuename to retrieve settings
strKeyPath = "Software\Policies\Microsoft\Windows\System\Power"
strValueName = "PromptPasswordOnResume"
oReg.GetDWORDValue HKCU,strKeyPath,strValueName,dwValue
'Return a failure exit code if entry does not exist
If IsNull(dwValue) Then
Wscript.Echo "The value is either Null or could not be found in the registry."
WScript.Quit 1
'Return a failure exit code if value does not equal STIG setting
ElseIf dwValue <> 1 Then
Wscript.Echo "This is a finding. ", strValueName,"=", dwValue
WScript.Quit 1
'Return a passing exit code if value matches STIG setting
ElseIf dwValue = 1 Then
Wscript.Echo "This is not a finding. "
WScript.Quit 0
End If
All this is what I ultimately came up with to resolve my issue.
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS = &H80000003
'Set the local computer as the target
strComputer = "."
'set the objRegistry Object
Set objRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
'Enumerate All subkeys in HKEY_USERS
objRegistry.EnumKey HKEY_USERS, "", arrSubkeys
'Define variables
strKeyPath = "\Software\Microsoft\Windows\CurrentVersion\Policies\Attachments"
strValueName = "HideZoneInfoOnProperties"
strSID = "S-1-5-21-\d*-\d*-\d*-\d{4,5}\\"
strValue = 1
f = True
For Each i in arrSubKeys
Set objRegExp = New RegExp
objRegExp.IgnoreCase = True
objRegExp.Global = True
objRegExp.Pattern = strSID
Set colMatches = objRegExp.Execute(i + strKeyPath)
For Each objMatch In colMatches
objRegistry.GetDWORDValue HKEY_USERS,i + strKeyPath,strValueName,dwValue
If IsNull(dwValue) Then
WScript.Echo "This is a finding, the key " & i + strKeyPath & "\" & strValueName & " does not exist."
f = False
ElseIf dwValue <> strValue Then
WScript.Echo "This is a finding, the " & i + strKeyPath & "\" & strValueName & ": " & dwValue & " does not equal REG_DWORD = " & strValue & "."
f = False
ElseIf dwValue = strValue Then
WScript.Echo "This is not a finding " & i + strKeyPath & "\" & strValueName & " = " & dwValue
End If
Next
Next
If f Then
WScript.Quit 0
Else
WScript.Quit 1
End If
You don't need recursion here. Simply iterate over the subkeys of HKEY_USERS and (try to) read the value. The return code of GetDWORDValue() will indicate whether or not the value could be read.
Const HKEY_USERS = &h80000003
subkey = "Software\Policies\Microsoft\Windows\System\Power"
name = "PromptPasswordOnResume"
computer = "."
Set reg = GetObject("winmgmts://" & computer & "/root/default:StdRegProv")
reg.EnumKey HKEY_USERS, "", sidList
For Each sid In sidList
key = sid & "\" & subkey
rc = reg.GetDWORDValue(HKEY_USERS, key, name, val)
If rc = 0 Then
If val = 1 Then
WScript.Echo "OK"
WScript.Quit 0
Else
WScript.Echo "Not OK"
WScript.Quit 1
End If
End If
Next
I am not sure if i got you right. If it is that you want to search in the HKU not in the HKCU, then the point is that an account in HKU is mapped to HKCU. Like in your case S-1-5-21* will be mapped to HKCU. You can check it by modifying an entry in HKCU and that will be reflected in HKU(S-1-5-21*) and vice-a-versa.

How to find out Outlook account info in Registry with VBScript?

I'm trying to create a report of User Accounts info on the members of an AD I manage. Specifically I need what accounts are configured on their Outlook installation; What kind of protocol are they using (POP/IMAP) and where are the associated PST files stored for backup purposes. I reckon I can deploy a VBScript on all machines which can write to a file in a shared location and I can then retrive that file.
I found some scripts online which can find the PST file location in HKCU..\Windows Messaging Subsystem\Profiles but couldn't understand how they were parsing the Hex keys. If I can figure that out, I can probably get the other info stored on the subkeys.
Any help on solving this would be appreciated.
Finally figured it out using pointers online. This basically loops down to three levels in the registry from a specified subkey and writes it to a file.
const HKCU = &H80000001
Const REG_SZ = 1
Const REG_EXPAND_SZ = 2
Const REG_BINARY = 3
Const REG_DWORD = 4
Const REG_MULTI_SZ = 7
strComputer = "."
Set StdOut = WScript.StdOut
Dim objFSO :Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim objPSTLog :Set objPSTLog = objFSO.OpenTextFile("%temp%\pst.log",8,True)
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" &_
strComputer & "\root\default:StdRegProv")
strKeyPath = "Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\"
oReg.EnumKey HKCU, strKeyPath, arrSubKeys
For Each subkey In arrSubKeys
objPSTLog.WriteLine(subkey)
strkeyPath1 = strkeyPath & subkey 'Outlook
oReg.EnumKey HKCU, strKeyPath1, arrSubKeys1
if IsArray(arrSubKeys1) Then
For Each subkey1 In arrSubKeys1
strkeyPath2 = strkeyPath1 & "\" & subkey1 'Outlook\8bce72417aa40d418ab879690e9b39cc etc
oReg.EnumKey HKCU, strKeyPath2, arrSubKeys2
if IsArray(arrSubKeys2) Then
For Each subkey2 In arrSubKeys2
objPSTLog.WriteLine(subkey2)
strkeyPath3 = strkeyPath2 & "\" & subkey2 'Outlook\8bce72417aa40d418ab879690e9b39cc\0000001 etc
oReg.EnumValues HKCU, strKeyPath3, arrValueNames, arrTypes
if IsArray(arrValueNames) Then
For i = lBound(arrValueNames) To uBound(arrValueNames)
strValueName = arrValueNames(i)
Select Case arrTypes(i)
' Show a REG_SZ value
'
Case REG_SZ
oReg.GetStringValue HKCU, strKeyPath3, strValueName, strValue
objPSTLog.WriteLine(" " & strValueName & " (REG_SZ) = " & strValue)
' Show a REG_EXPAND_SZ value
'
Case REG_EXPAND_SZ
oReg.GetExpandedStringValue HKCU, strKeyPath3, strValueName, strValue
objPSTLog.WriteLine(" " & strValueName & " (REG_EXPAND_SZ) = " & strValue)
' Show a REG_BINARY value
'
Case REG_BINARY
oReg.GetBinaryValue HKCU, strKeyPath3, strValueName, arrBytes
strBytes = ""
For Each uByte in arrBytes
uByte = Hex(uByte)
strBytes = strBytes & uByte & " "
Next
objPSTLog.WriteLine(" " & strValueName & " (REG_BINARY) = " & strBytes)
' Show a REG_DWORD value
'
Case REG_DWORD
oReg.GetDWORDValue HKCU, strKeyPath3, strValueName, uValue
objPSTLog.WriteLine(" " & strValueName & " (REG_DWORD) = " & CStr(uValue))
' Show a REG_MULTI_SZ value
'
Case REG_MULTI_SZ
oReg.GetMultiStringValue HKCU, strKeyPath3, strValueName, arrValues
objPSTLog.WriteLine(" " & strValueName & " (REG_MULTI_SZ) =")
For Each strValue in arrValues
objPSTLog.WriteLine(" " & strValue)
Next
End Select
Next
End If
strKeyPath3=""
Next
End If
strKeyPath2=""
Next
strkeyPath1 = ""
End If
Next
objPSTLog.WriteLine("")
objPSTLog.WriteLine("--------------------------------------------------------------------------------------------------------------")
objPSTLog.WriteLine("")
objPSTLog.close
MsgBox "Script Run Successful"
It still writes the Hex values. The PST Location is stored in "Delivery Store EntryID", Account name and email in "Account Name" & "Email". All are stored as REG_BINARY.
How do I get the ASCII output in the REG_BINARY Case in the last loop?

Resources