I am new to working with the Registry and have spent the past few days working through many different code examples attempting to learn how to access different types of values at different levels in the Registry hierarchy. I have built all the examples I could find on Microsoft Learn and a few others. But all the examples only appear to demonstrate how to open, close, read, write and delete first level/tier (i.e. Root > subkey)? I also looked through examples that appear here on SO but haven't found anything that answers my questions?
The Problem
When third party software is updated any software Paths which contain version information (i.e. Version, Year, etc.) change. This prevents icon extraction from hard-coded Paths which have not been updated. As a workaround for this issue I am trying to learn how to extract Paths directly from the Registry, load them at runtime and then extract software icons from updated Paths. Please see my related (i.e. first) question:
Third-Party-Software-Icons-And-Paths
What I Need
I am trying to extract, for example, the full list of Paths found in the Registry folder:
Computer\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Compatibility Assistant\Store
As in the screenshot above, this folder is 7 levels deep in the hierarchy. I want the full list of Paths (i.e. 159) on the left of the screen? Double clicking the item shows a dialog which calls this value "Value Name." I don't want the Binary data here just the Paths as strings. How do I achieve this?
Also, another Registry folder I'm interested in is:
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
I want to get the Software/Program Name from each subfolder and then the Default Value and the Path Value from each program subfolder in the App Paths folder. How do I achieve this?
After much studying, I can now read top level (i.e. Root > first level subkey), but I can't find any examples of how to get deeper than that? I am especially interested in examples which use some sort of shorthand rather than writing out everything longhand.
What I have Tried
I have built all the Registry code examples I could find on Microsoft learn and others. But I really would appreciate some real code examples and I would like to understand what I need to do so I can learn from the examples! I also would appreciate any links which both explain how to achieve this and give code examples! Thank you!
Example 1:
Dim rkey As RegistryKey = Registry.ClassesRoot
' Retrieve all the subkeys for the specified key.
Dim names As String() = rkey.GetSubKeyNames()
Example 2: Get Installed Software List:
Dim appPATH As String = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
Using rk As RegistryKey = Registry.LocalMachine.OpenSubKey(appPATH)
For Each name As String In rk.GetSubKeyNames()
Using sk As RegistryKey = rk.OpenSubKey(name)
Dim displayName = sk.GetValue("DisplayName")
Dim installDate = sk.GetValue("InstallDate")
Dim version = sk.GetValue("DisplayVersion")
If displayName IsNot Nothing Then
If installDate IsNot Nothing AndAlso version IsNot Nothing Then
Console.WriteLine($"Application Name: {displayName}")
Console.WriteLine($"Version: {version}")
Console.WriteLine($"Installed Dateļ¼ {installDate}")
Console.WriteLine()
ListView1.Items.Add(New ListViewItem(New String() {displayName, version, installDate}))
Else
Console.WriteLine($"Application Name: {displayName}")
Console.WriteLine()
ListView1.Items.Add(New ListViewItem(New String() {displayName}))
End If
End If
End Using
Next
End Using
Console.ReadLine()
Just found some code which I attempted to adapt, but it throws an exception?
Dim regkey As RegistryKey = Registry.LocalMachine.OpenSubKey("Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe", False)
For Each s As [String] In regkey.GetValueNames("Path") 'Tried both (Default) and Path??? Also, tried changing original from regkey.GetSubKeyNames() to regkey.GetValueNames()???
Console.WriteLine(s)
Next
EXCEPTION: System.NullReferenceException: 'Object reference not set to an instance of an object.'
Partially Working Code:
The following code works, but only gets a single Path/String from a list of 159? I tried creating a For Each loop, but I'm not sure how to write it because my attempt just gives me 159 duplicates of the same Path/String? Can anyone help me with this?
Dim pRegKey As RegistryKey = Registry.CurrentUser
pRegKey = pRegKey.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Compatibility Assistant\\Store")
Dim val As Object = pRegKey.GetValueNames(Nothing)
Console.WriteLine("Default Value:" & val.ToString)
This is just one Path/String from a list of 159:
RESULT: Default Value:C:\Users\jmwil\Downloads\WPSOffice_11.2.0.10114.exe
My Attempt at For Each Loop:
For Each v As Object In pRegKey.ToString
Console.WriteLine("Default Value:" & val.ToString)
Next
windows-registry-in-vb.net-part-2
Working Code
The following code works to get a list of subkey Names, but I'm still searching for a way to get a list of the values from the subkeys as per the bottom half of the screenshot.
Dim keys As Microsoft.Win32.RegistryKey =
My.Computer.Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths")
For Each str As String In keys.GetSubKeyNames
MsgBox(str & vbCrLf)
Next
Partial Result
7zFM.exe
Acrobat.exe
AcrobatInfo.exe
Adobe Bridge.exe
chrome.exe
cmmgr32.exe
devenv.exe
dfshim.dll
fsquirt.exe
IEDIAG.EXE
IEDIAGCMD.EXE
IEXPLORE.EXE
Partial Example of Result I'm Looking For From First RegKey:
On the top half of the screenshot (above) the Compatibility Assistant subkey 'Store' has a list of 159 Paths/Strings on the left. I want to be able to extract this list of Paths/Strings as follows?
C:\Drivers\Flash\20211908.23032253\DKCN53WW.exe
C:\Program Files (x86)\Common Files\Adobe\ARM\1.0\AdobeARM.exe
C:\Program Files (x86)\Common Files\Microsoft Shared\MSEnv\VSLauncher.exe
C:\Program Files (x86)\e-Sword\e-Sword.exe
C:\Program Files (x86)\IObit\Advanced SystemCare\ASC.exe
Partial Example of Result I'm Looking For From Second RegKey:
On the bottom half of the screenshot (above) the AppPaths subkey has 39 subkeys. Each subkey has two values, Default and Path. I want to extract the subkey Name, Default Value and Path value for each of the 39 subkeys?
SubKey Name: 7zFM.exe
DefaultValue: C:\Program Files\7-Zip\7zFM.exe
PathValue: C:\Program Files\7-Zip\
SubKey Name: Acrobat.exe
DefaultValue: C:\Program Files\Adobe\Acrobat DC\Acrobat\Acrobat.exe
PathValue: C:\Program Files\Adobe\Acrobat DC\Acrobat\
SubKey Name: AcrobatInfo.exe
DefaultValue: C:\Program Files\Adobe\Acrobat DC\Acrobat\AcrobatInfo.exe
PathValue: C:\Program Files\Adobe\Acrobat DC\Acrobat\
The following code snippet now gets the full list of 39 subkey names, but repeats the subkey names twice and the Default and Path values from the first subkey (i.e. 7zFM.exe) are repeated for each of the subkeys (See Partial Result below)? Can anyone help me on how to write the loop I need to get the names of the 39 subkeys and their Default and Path values? I've been working on this for over a week now and I still can't find a way to get it working correctly? Also, I still need to find a way to get the values in the top half of the screenshot? Any help would be greatly appreciated! :-)
Partial Result
Name;Value
7zFM.exe;C:\Program Files\7-Zip\7zFM.exe
7zFM.exe;C:\Program Files\7-Zip\
Acrobat.exe;C:\Program Files\7-Zip\7zFM.exe
Acrobat.exe;C:\Program Files\7-Zip\
AcrobatInfo.exe;C:\Program Files\7-Zip\7zFM.exe
AcrobatInfo.exe;C:\Program Files\7-Zip\
Adobe Bridge.exe;C:\Program Files\7-Zip\7zFM.exe
Adobe Bridge.exe;C:\Program Files\7-Zip\
chrome.exe;C:\Program Files\7-Zip\7zFM.exe
chrome.exe;C:\Program Files\7-Zip\
e.g.
REGISTRY PATH: Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\
'GET SUBKEY NAMES:
Dim keys As Microsoft.Win32.RegistryKey =
My.Computer.Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths")
'GET VALUES:
Dim FontKey As Microsoft.Win32.RegistryKey = My.Computer.Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\7zFM.exe")
For Each str As String In keys.GetSubKeyNames
For Each ValueName As String In FontKey.GetValueNames()
Dim Value As Object = FontKey.GetValue(ValueName) 'Get the value (data) of the specified value name.
If Value IsNot Nothing Then 'Make sure it exists.
ListView1.Items.Add(New ListViewItem(New String() {str, Value.ToString}))
End If
Next
Next
FontKey.Close()