VB.NET - Edit Windows Registry Value - vb.net

I'm trying to set my program as the "Default Program" for all Text Files so in order to do this I need to change the (Default) value which is: %SystemRoot%\system32\NOTEPAD.EXE %1 to C:\Program.exe %1 in HKEY_CLASSES_ROOT\txtfile\shell\open\command\
I do this by using this code:
Dim regKey As RegistryKey
regKey = Registry.ClassesRoot.OpenSubKey("txtfile\shell\open\command", True)
regKey.SetValue("(Default)", "C:\Program.exe %1", RegistryValueKind.ExpandString)
regKey.Close()
The problem is that when I do it, it creates another key with the Expand String called "(Default)" rather than editing the "(Default)" key which is already there. How can I EDIT rather than just create?

This is explicitly mentioned in a NOTE in the MSDN article for RegistryKey.SetValue():
A registry key can have one value that is not associated with any name. When this unnamed value is displayed in the registry editor, the string "(Default)" appears instead of a name. To set this unnamed value, specify either null or the empty string ("") for the name.
Fix:
regKey.SetValue("", "C:\Program.exe %1", RegistryValueKind.ExpandString)

Related

Registry Hierarchy - Read Different Types Of Values From All Levels of Subkeys

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()
InstalledSoftwareList
MicrosoftLearn
Listcontentsofalocationintheregistry

windows dropdown menu pass file name to vb.net program

I have a few files that pending on factors may require an alternate-variation to be used. The selection of the right file starts at standard windows directory C:\Drawings in my case, So I know that we can add items to the windows backbround context menu as follows:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\txtfile\shell\mymenu]
#="test123"
[HKEY_CLASSES_ROOT\txtfile\shell\mymenu\command]
#="%SystemRoot%\\system32\\NOTEPAD.EXE %1"
However (and im not sure even if this is possible) i would like to get the name of the file that was cliked and use it in my vb.net application for example a textbox wich displays that files name.
dose anybody know if i can do this? and how?
First you'll have to get the command line arguments, which can be done in a few different ways but I prefer to use Environment.GetCommandLineArgs():
Dim Arguments() As String = Environment.GetCommandLineArgs()
Then you must check that there's actually an argument to read. The very first argument (index 0) is always the path to your application, therefore we must check that it contains at least two arguments to be sure that there is also one passed to your app.
If Arguments.Length >= 2 Then
Finally you just get the path to the file from the second argument, and call IO.Path.GetFileName() on that:
Dim FilePath As String = Arguments(1) 'Second argument has index 1.
Dim FileName As String = IO.Path.GetFileName(FilePath)
If you don't want the file's path at all you can just go ahead and do:
Dim FileName As String = IO.Path.GetFileName(Arguments(1))
Full code:
Dim Arguments() As String = Environment.GetCommandLineArgs()
If Arguments.Length >= 2 Then
Dim FilePath As String = Arguments(1) 'Second argument has index 1.
Dim FileName As String = IO.Path.GetFileName(FilePath)
'Do your stuff here.
End If

Change system registry values on vb.net

I want to change my computer's system registry value via vb.net
Dim regKey As RegistryKey
regKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Ole", True)
regKey.SetValue("EnableDCOM", "Y")
regKey.Close()
I've tried the above, however it gives no error but it simply doesn't change the value...
I hardly use VB, but I believe the below is the correct approach.
Dim autoshell = My.Computer.Registry.LocalMachine.OpenSubKey("Software\Microsoft\Windows NT\CurrentVersion\Winlogon", True)
'' Set the value to 0
autoshell.SetValue("autorestartshell", 0)
autoshell.Close()
If you experience errors, you need to check that:
You have permissions to read/write to the registry.
The subkey you are trying to change actually exists.
You should also consult the MSDN VB Documentation.

How to specify a path with spaces for StreamWriter

In VB.Net, how do I provide the StreamWriter constructor with a path that includes spaces? StreamWriter("""C:\Users\Public\Public Users\file.txt""") does not work.
Here is a working code example:
Dim fs As New System.IO.StreamWriter("e:\test 123.txt")
fs.Write("hello")
fs.Close()
UPDATE:
The new example for folder with space(s):
'this is your filename
Dim Filename As String = "e:\folder with space\test 123.txt"
'this is your folder
Dim Folderpath As String = System.IO.Path.GetDirectoryName(Filename)
'now do checking if the folder exists, if not create the folder
If System.IO.Directory.Exists(Folderpath) = False Then
System.IO.Directory.CreateDirectory(Folderpath)
End If
'now create the file as usual
Dim fs As New System.IO.StreamWriter("e:\folder with space\test 123.txt")
fs.Write("hello")
fs.Close()
The reason for your code didn't compile because you have not create the folder before creating the file, ie that folder must be existed before you can create your file.
You don't put quotes around the string you pass to the StreamReader constructor. Quotes are only used when you use, say, the command line. Or anything else that uses spaces as separators between arguments. The program requires those double quotes to recognize an argument with an embedded space.
Not necessary here, there's no ambiguity since the argument only takes the path to a single file. The only exception to that rule that I know of is the ProcessStartInfo.Arguments property.
So, just put single double quotes around the string, the syntax that the compiler requires. Your real problem is the name of the folder. Windows Explorer shows a different name for the folders in c:\users\public. For example c:\users\public\videos is displayed in the Explorer window as "Public Videos". It's trying to be helpful by expanding the abbreviated name. Your program however has to use the real folder name. Which is probably "users", not "Public Users". To find out for sure, use the command line (cmd.exe). Use cd \users\public and dir /a.
Last but not least, that folder has a different name on different versions of Windows. You should use Environment.GetFolderPath(). "Public Users" isn't a standard folder name however, not sure why you are using it.

Surest way to detect if an application has been installed on a Windows PC in a VB.NET app?

I know the default install path of the app and the name of the .exe file, but is there a way to see if it is actually installed?
I've seen suggestions for checking registry entries, but I don't know if this app uses any or if if varies for different users on different pc's.
Many of the registy entries have no default values set. I prefer not to dive too deep and have to rely on a value for the font setting.
I'd like to know if "App_Name" exists. I can't rely on it having a default value because it never does. Since I'm using .GetValueKind, I don't have to worry about "AboutSiteUR" having any value set assuming if it has a type it actually exists. Otherwise, I'm assuming the Try/Catch will trap the IO.IORegistry type error (I'm not sure about that one.).
Dim sDisplay_Reg_Value As String
Dim Everest_Registry As Microsoft.Win32.RegistryKey = _
My.Computer.Registry.CurrentUser.OpenSubKey("Software\Company_Name\App_Name")
Try
sDisplay_Reg_Value = CType(Everest_Registry.GetValueKind("AboutSiteUR"), String)
'If the key does not exist Everest_Registry will contain Nothing, otherwise the returned key will be populated. Try this:
Dim Everest_Registry As Microsoft.Win32.RegistryKey = _
My.Computer.Registry.CurrentUser.OpenSubKey("Software\Microsoft\Internet Explorer")
If Everest_Registry Is Nothing Then
'key does not exist
MsgBox("Key does not exist")
Else
'key is valid, display actual name
MsgBox(Everest_Registry.Name)
End If
Does the application show up in the "Add/Remove programs" control panel? If yes, then there are definitely some registry entries you can look at that would not vary by user.
use regedit.exe to search the subkeys of CLSIDs key, if the application folder appears in any of the subkeys, then this also would be something that doesn't vary by user.
Or your could ask them. I used to work for a company that made software you could buy at Best Buy, etc. In their software, there was a specific registry key that each application created so that all of their apps could find each other.