In my c# program, I'm running a python process. Currently I'm using a hardcoded path for the python.exe, but I want to use the windows registry to return the path to me.
I have found the python path info in the Windows registry under:
HKEY_CURRENT_USER\Software\Python\PythonCore\3.7-32\InstallPath
with some googling I found the following solution:
https://stackoverflow.com/a/18234755/7183609
but when I run my code the variable key is always null
try
{
using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Software\\Python\\PythonCore\\3.7-32\\InstallPath"))
{
if (key != null)
{
// do things
}
}
}
catch (Exception ex)
{
// do other things
}
Am I doing something wrong, do I need to add something to make it work?
John Wu pointed out that LocalMachine was wrong.
changed
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(#"HKEY_CURRENT_USER\Software\Python\PythonCore\3.7-32\InstallPath"))
to
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(#"HKEY_CURRENT_USER\Software\Python\PythonCore\3.7-32\InstallPath"))
Use Registry.CurrentUser instade of Registry.LocalMachine
try
{
using (RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\Python\\PythonCore\\3.7-32\\InstallPath"))
{
if (key != null)
{
// do things
}
}
}
catch (Exception ex)
{
// do other things
}
Related
I have a small subroutine to check for the existence of a required server program, as follows:
private bool IsProgramInstalled(string programDisplayName)
{
string logstr = string.Format("Checking install status of {0}....", programDisplayName);
RegistryKey rk = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Bridge Club Utilities");
foreach (string s in rk.GetSubKeyNames())
{
Console.WriteLine(s);
if (s != null)
{
if (s.Equals(programDisplayName))
{
AppendToLog(logstr + " INSTALLED");
return true;
}
}
}
AppendToLog(logstr + " NOT INSTALLED", Color.Red);
return false;
}
I have installed the program containing the above subroutine on many Windows boxes with no problems, but one customer receives an 'Unhandled Exception' error on program startup, as shown below:
When I loaded VS2022 on the customer's machine and ran it in debug mode, the exception appears on the line that sets RegistryKey rk, as shown below:
So I thought this user had maybe installed the required server program (BridgeComposer) in the wrong place, or the registry was screwed up somehow, or there was a permissions issue. I tried running my app in 'administrative mode', but this did not solve the problem.
Next, I tried to see if the user's PC had the same registry entries as my PC, and it appears that they do. If I manually navigate to 'Computer\HKEY_LOCAL_MACHINE\SOFTWARE\RegisteredApplications' on both machines, I see the same entry for 'BridgeComposer' as shown below:
Clearly I'm doing something wrong/stupid, but I have no clue what it is. Any pointers/clues would be appreciated.
Most likely your program is running as 32-bit on a 64-bit computer and is therefore searching in HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node.
There are a number of ways one can approach this:
Use Registry.OpenBaseKey and specify the desired Registry View.
Compile for AnyCPU, but uncheck Prefer 32-bit (Project => <project name> Properties... => Build => Uncheck Prefer 32-bit)
Compile for 64-bit
Option 1:
Note: The following is untested, but should work - it's a slight modification of the code in your OP.
private bool IsProgramInstalled(string programDisplayName, RegistryView regView = RegistryView.Registry64)
{
string logstr = string.Format("Checking install status of {0}....", programDisplayName);
using (RegistryKey localKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, regView))
{
if (localKey != null)
{
using (RegistryKey rk = localKey.OpenSubKey(#"SOFTWARE\Bridge Club Utilities"))
{
if (rk != null)
{
foreach (string s in rk.GetSubKeyNames())
{
Console.WriteLine(s);
if (s != null)
{
if (s.Equals(programDisplayName))
{
AppendToLog(logstr + " INSTALLED");
return true;
}
}
}
}
}
}
}
AppendToLog(logstr + " NOT INSTALLED", Color.Red);
return false;
}
Im using the Microsoft.Win32.Registry class. Im trying to make a if RegKey exist statement but don't know how
I want something like this:
RegistryKey key = Registry.CurrentUser.CreateSubKey(#"SOFTWARE\test");
if(key.keyExist("yourKey")) Console.WriteLine("yourKey exist!");
As far as I know, the SubKey is stored in a path in the system.
So you can do something like this to check out if the SubKey exists:
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\test"))
{
if (key != null)
{
Console.WriteLine("yourKey exist!");
}
else
{
// e.g. create SubKey
}
}
I can get/set registry values using the Microsoft.Win32.Registry class. For example,
Microsoft.Win32.Registry.SetValue(
#"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run",
"MyApp",
Application.ExecutablePath);
But I can't delete any value. How do I delete a registry value?
To delete the value set in your question:
string keyName = #"Software\Microsoft\Windows\CurrentVersion\Run";
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true))
{
if (key == null)
{
// Key doesn't exist. Do whatever you want to handle
// this case
}
else
{
key.DeleteValue("MyApp");
}
}
Look at the docs for Registry.CurrentUser, RegistryKey.OpenSubKey and RegistryKey.DeleteValue for more info.
To delete all subkeys/values in the tree (~recursively), here's an extension method that I use:
public static void DeleteSubKeyTree(this RegistryKey key, string subkey,
bool throwOnMissingSubKey)
{
if (!throwOnMissingSubKey && key.OpenSubKey(subkey) == null) { return; }
key.DeleteSubKeyTree(subkey);
}
Usage:
string keyName = #"Software\Microsoft\Windows\CurrentVersion\Run";
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true))
{
key.DeleteSubKeyTree("MyApp",false);
}
RegistryKey registrykeyHKLM = Registry.LocalMachine;
string keyPath = #"Software\Microsoft\Windows\CurrentVersion\Run\MyApp";
registrykeyHKLM.DeleteValue(keyPath);
registrykeyHKLM.Close();
RegistryKey.DeleteValue
string explorerKeyPath = #"Software\TestKey";
using (RegistryKey explorerKey = Registry.CurrentUser.OpenSubKey(explorerKeyPath, writable: true))
{
if (explorerKey != null)
{
explorerKey.DeleteSubKeyTree("TestSubKey");
}
}
I Needed something a little different, I just needed to delete everything a key contained. Therefore the below
Registry.LocalMachine.DeleteSubKeyTree(#"SOFTWARE\YourNeededKeyThatHasMany\");
Note that here its using LocalMachine so it's looking in "HKEY_LOCAL_MACHINE" for the Key to delete its SubTreeKeys. Was simpler for me to do this and would've liked to see this simple answer here.
I need to check the availability and also read some registry key by CLR(C#), registry keys already written by another application.
As a sample:
public bool IsKeyAvailable(string KeyID)
{
string keyToRead = #"Software\myRoot\myApp\" + KeyID;
using (RegistryKey regKey = Registry.CurrentUser.OpenSubKey(keyToRead, RegistryKeyPermissionCheck.ReadSubTree))
{
if (regKey == null)
return false;
return true;
}
}
Checking & reading code are working fine outside of the CLR, but within the CLR the same code doesn't working, Already signed the CLR and assembly created WITH PERMISSION_SET = UNSAFE.
What could be missed for this scenario to find and read my registry keys by CLR?
Use this code :
Registry.LocalMachine.OpenSubKey("SOFTWARE", true);
RegistryKey masterKey = Registry.LocalMachine.CreateSubKey("SOFTWARE\yourapp\yourkey");
string value = "";
if (masterKey != null)
{
value = masterKey.GetValue("yourvalue").ToString();
}
masterKey.Close();
I am using Visual C# 2010 and am having problems setting registry keys. I assumed this was to do with the fact that I wasn't running it as admin at first but i have tried building the Release and then right clicking the exe and selecting 'run as administrator' to no avail.
I also tried using the RegistryPermission class which didn't seem to make any difference.
Here is the code:
RegistryKey rkey = Registry.LocalMachine;
// RegistryPermission f = new RegistryPermission(
// RegistryPermissionAccess.Write | RegistryPermissionAccess.Read,
// #"HKEY_LOCAL_MACHINE\SOFTWARE\Company\Product");
/**********************/
/* set registry keys */
/**********************/
RegistryKey wtaKey = rkey.OpenSubKey(#"SOFTWARE\Company\Product", true);
try
{
wtaKey.SetValue("key1", 123);
wtaKey.SetValue("key2", 567);
wtaKey.SetValue("key3", textbox.Text);
wtaKey.SetValue("key4", "some string");
}
catch (UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
return;
}
This gives me the error message from the exception each time I run it, even with 'run as administrator'. Any ideas how I can get around this? It seems strange because my standard user account allows me to go into regedit and manually change these values no problem.
This works :)
First:
You should be using CreateSubKey rather than OpenSubKey.
Second:
It was not an administrative issue that you were experiencing, rather, you simply needed to add another "\" to the end of your registry path.
private void button1_Click(object sender, EventArgs e)
{
RegistryKey rkey = Registry.LocalMachine;
RegistryPermission f = new RegistryPermission(
RegistryPermissionAccess.Write | RegistryPermissionAccess.Read,
#"HKEY_LOCAL_MACHINE\SOFTWARE\Company\Product");
/**********************/
/* set registry keys */
/**********************/
RegistryKey wtaKey = rkey.CreateSubKey(#"SOFTWARE\Company\Product\");
try
{
wtaKey.SetValue("key1", 123);
wtaKey.SetValue("key2", 567);
wtaKey.SetValue("key4", "some string");
}
catch (UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
return;
}
}