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;
}
}
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;
}
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
}
I am trying to access a registry key in LocalMachine. The code works on my machine, but does not work on my friend's. I have looked at his registry and the key is in the same place as mine.
I tried to put try{} catch{} blocks around OpenBaseKey to see if I can see which exception is being thrown, and none of the exceptions are being caught (Makes me think that it doesn't get past OpenBaseKey.
So, what is happening on my friend's machine, the application will run until my MessageBox.Show("Getting Registry Key") and then crash. I have included a screen shot of the error box.
What could be causing this?
string path = string.Empty;
const string hfss_key_name = #"SOFTWARE\Ansoft\HFSS\2014.0\Desktop";
const string hfss_value = "LibraryDirectory";
MessageBox.Show("Getting Registry Key");
RegistryKey localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
localKey = localKey.OpenSubKey(hfss_key_name);
if(localKey != null)
{
path = localKey.GetValue(hfss_value).ToString();
path += #"\HFSS\userlib\";
}
Error Window:
I found the issue, I had the wrong hfss_value. For some reason his and my value are different for that LibraryDirectory. Thanks for all the help.
As it has been pointed out you need to catch the exception to determine why there is a problem. Otherwise, your application can crash exactly as you experience it.
But even without any details about the exception with some code inspection it is perhaps possible to reveal the source of the exception.
Unless you have some weird security settings reading from the registry should be possible and you are careful to check for existence of the key. However, the call to GetValue will return null if the value is missing and calling ToString on null will throw a NullReferenceException. The next line of code should not throw an exception even if path is null.
So changing this code
path = localKey.GetValue(hfss_value).ToString();
path += #"\HFSS\userlib\";
into this code
var value = localKey.GetValue(hffs_value);
if (value != null)
path = value + #"\HFSS\userlib\";
should fix the problem if I am not mistaken.
You probably don't have permissions to get to the key; it is crashing because you're not catching exception thrown.
Change your code to catch the exception and it should help you figure it out:
string path = string.Empty;
const string hfss_key_name = #"SOFTWARE\Ansoft\HFSS\2014.0\Desktop";
const string hfss_value = "LibraryDirectory";
MessageBox.Show("Getting Registry Key");
try
{
RegistryKey localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
localKey = localKey.OpenSubKey(hfss_key_name);
if (localKey != null)
{
path = localKey.GetValue(hfss_value).ToString();
path += #"\HFSS\userlib\";
}
}
catch (SecurityException secex)
{
MessageBox.Show("SecurityException: " + secex);
}
catch (UnauthorizedAccessException uex)
{
MessageBox.Show("UnauthorizedAccessException: " + uex);
}
catch (Exception ex)
{
MessageBox.Show("Exception: " + ex);
}
Make sure you are administrator on your friends machine. LocalMachine generally needs admin privileges. you might check out http://msdn.microsoft.com/en-us/library/windows/desktop/ms724878(v=vs.85).aspx
If you run your app with administrator privileges (right mouse button -> Run as administrator) and it works, it's a permission problem.
If it still crashes, most likely it's because you have a 64 bit Windows, while he has a 32 bit Windows or vice versa.
I'm writing an app that needs to work every time the computer starts after the user installs it. i tried to do it on the installer calss in the afterInstall event but the installer puts it self to the registry and runs when windows restarts, so I tried to do it with the commited event and got the same results. After that I chenged the commited property installer class to false but then the commited evet dont fire. My last try was to run the app after it installs and then let it write itself to the registry and a strange thing happened it did writh to the registry but no to the place I wanted it to be does anyone know why that is and how can I fix it?
My code:
bool registry = true;
RegistryKey rkSubKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", false);
string[] values = rkSubKey.GetValueNames();
foreach(string name in values)
{
if (name.Equals("appName"))
registry = false;
}
if (registry)
{
RegistryKey rkApp = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
rkApp.SetValue("appName", Application.ExecutablePath.ToString());
DialogResult r = MessageBox.Show("The system now needs to restart your computer whould you like to do it now?", "Restart is needed", MessageBoxButtons.YesNo);
if (r == DialogResult.Yes)
{
System.Diagnostics.Process.Start("ShutDown", "/r");
}
return;
}
mainModule.start();
Have you tried to open the subroot key smth like this:
var HKLM = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32);
and then get your subkey:
var baseKey = HKLM.OpenSubKey(...<the path here>..)
?
I'm using the following code
private static string GetLogonFromMachine(string machine)
{
//1. To read the registry key that stores this value.
//HKEY_Local_Machine\Software\Microsoft\Windows NT\CurrentVersion\WinLogon\DefaultUserName
var rHive = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, machine);
var rKey = rHive.OpenSubKey(#"Software\Microsoft\Windows NT\CurrentVersion\WinLogon");
var rItem = rKey.GetValue("DefaultUserName");
return rItem.ToString();
}
and I've confirmed that my user has access, the MVC site is using integrated authentication and that the listed REG_SZ "DefaultUserName" has a value on the machine targetted but rItem doesn't grab a value.
I guess I'm doing something silly and I'd love to know what!
I was indeed being silly. I wasn't sorting the list of machine names before use and so I was looking at the registry of the wrong machine. The machine that was actually in focus was correctly returning "".
I've ended up with
private static string GetLogonFromMachine(string machine)
{
//1. To read the registry key that stores this value.
//HKEY_Local_Machine\Software\Microsoft\Windows NT\CurrentVersion\WinLogon\DefaultUserName
RegistryKey rHive;
try
{
rHive = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, machine);
}
catch (IOException)
{
return "offline";
}
var rKey = rHive.OpenSubKey("Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon\\");
if (rKey == null)
{
return "No Logon Found";
}
var rItem = rKey.GetValue("DefaultUserName");
return rItem==null ? "No Logon Found" : rItem.ToString();
}