Strange issue with Registry.GetValue() - c#

I have used the following code to read "UserName" and "Password" from registry:
RegistryKey key = Registry.LocalMachine.OpenSubKey(#"Software\Microsoft\MSCRM");
string username = key.GetValue("UserName").ToString();
string password = key.GetValue("Password").ToString();
key.Close();
However, it appears that sometimes GetValue() returns null that means "UserName" and "Password" keys do not exist. I have looked in windows registry but actually keys are there. The strange thing is that it happens from time to time.
Any ideas?

It could be that you sometimes run the application in 32 or 64 bits. Make sure the keys exists both under
"Software\Microsoft\MSCRM"
and
"Software\Wow6432Node\Microsoft\MSCRM"
If your application run as 32bits (x86 build) it will look in that area of the registry instead.

Related

C# Winform Registry set and get functions appear to work, but don't actually change the registry

I'm trying to use this registry hack I found online:
;Disables F1 key - Help and Support - in Windows 10
;Ramesh Srinivasan, Winhelponline.com
[HKEY_CURRENT_USER\SOFTWARE\Classes\Typelib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win32]
#=""
[HKEY_CURRENT_USER\SOFTWARE\Classes\Typelib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win64]
#=""
When I run it as a .reg command via Windows Explorer and watch the registry with regedit, it works as intended. Removing it is another registry file that simply removes the \0 subkey (and win32 and 64 with it). I'm trying to emulate this function with C# in a Winform using .net CORE:
private void CheckF1()
{
// Registry data from ;Ramesh Srinivasan, Winhelponline.com
RegistryKey F1key = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Classes\TypeLib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0");
// EGADS! It's active!
if (F1key == null)
{
fckF1RestoreBtn.Enabled = false;
fckF1KillBtn.Enabled = true;
fckF1Status.Text = "That creepy bugger is waiting and watching.";
}
else
{
fckF1RestoreBtn.Enabled = true;
fckF1KillBtn.Enabled = false;
fckF1Status.Text = "The F1-Help function had been put in it's place.";
}
}
private void fckF1KillBtn_Click(object sender, EventArgs e)
{
Registry.CurrentUser.CreateSubKey(#"SOFTWARE\Classes\Typelib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win32");
Registry.CurrentUser.CreateSubKey(#"SOFTWARE\Classes\Typelib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win64");
CheckF1();
}
private void fckF1RestoreBtn_Click(object sender, EventArgs e)
{
Registry.CurrentUser.DeleteSubKeyTree(#"SOFTWARE\Classes\Typelib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0");
CheckF1();
}
Weirdly the code "sees" a setting and responds like it should. Even to the point that whichever toggle position it was in on close it remembers when I load the file again. It's almost like it's playing along to screw with me. Regardless, when I watch the registry, none of my code has any actual effect though by all appearances it seems to work otherwise (it doesn't actually of course because the registry change isn't happening).
NOTE: I have already updated my manifest file for the project to include elevated permissions:
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Here's the breakpoint on the test statement to see if the subkeys are there that shows they are:
Meanwhile the registry location for the exact path shown in the debug doesn't have the 1.0\0 path at all:
I don't know how the code is reading phantom values. Someone closed my previous question pointing to another answer that didn't have any effect (Registry key deleted but still getting value from registry c#):
"Prefer 32 bit" was never checked for my project in the first place
Modifying my code as recommended had no effect
var key = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64)
.OpenSubKey(#"SOFTWARE\WOW6432Node\Classes\TypeLib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0");
Adding "Wow64Node" to the path makes no difference in execution.
EXPECTED BEHAVIOR
Checking to see if the HKEY_CURRENT_USER\SOFTWARE\Classes\Typelib{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0 path is present should return null if the \0 path is not present
Adding and removing the subkeys should show in the registry
So apparently HKEY_CURRENT_USERS is an alias. When the above code runs, it updates in HKEY_USERS under the specific logged in user. There's a question that talks about this behavior here: write registry to hkey_current_user instead of hkey_users
That said, the code appears to work, it's just that the registry doesn't update HKCU like when you run .reg commands. To verify it was working, I'd run the toggle that kills the keys then click them in Regedit and it would say they didn't exist. When I toggled back, I could click on them. So basically, it works (not sure if it required the "using" blocks as others suggested, but I see no reason to take them out).
Now my problem is that it points to the admin user and NOT the regular user because I'm running it and regedit as admin. It took forever to determine this based on running regedit as user in one case and admin in another. Bottom line, this won't work and I'll probably end up running .reg files in the command line instead.

deletesubkeytree not deleting registry folder

I want to delete a folder named EXAMPLE and all values in it in registry that is found under "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\EXAMPLE"
i have tried this ( with true at the end aswell )
Microsoft.Win32.Registry.LocalMachine.DeleteSubKeyTree(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\EXAMPLE");
and tried this
string keyName = #"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(keyName, true))
{
key.DeleteSubKeyTree("EXAMPLE", true);
}
They either throw me a null exception or argument exception.
How can i just delete an entire folder with all its keys ?
So that i can have the similar effect from batch :
REG DELETE "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\EXAMPLE" /f
The path is incorrect, Registry.LocalMachine doesn't have such a sub key #"HKEY_LOCAL_MACHINE\...". You need to start from "SOFTWARE\..".
string keyName = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
And from your feedback, your program is affected by the Registry Redirector, in which HKEY_LOCAL_MACHINE\Software is redirected to HKEY_LOCAL_MACHINE\Software\Wow6432Node for a 32-bit program, recompile your program from AnyCPU (Prefer 32-bit) to x64 gets rid of the redirection.
The mechanism of Registry Redirector varies on different Windows versions, so I leave this to you for further reading to understand why 64/32 matters in this case.

Reading registry keys from c#

I'm trying to fetch some data on the Office Click-To-Run currently installed.
I've read these posts : Can't Read Registry Key or OpenSubKey() returns null for a registry key that I can see in regedit.exe
I'm on Windows 10 64bit. My application is an Outlook add-in, so I can't change the target platform (32/64bit), it's the Host that determine if I'm running in 32bit or 64bit. So I've to handle both cases.
So I've this (test) code :
using (var hklmTest64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
{
var test = hklmTest64.GetValue(#"SOFTWARE\Microsoft\Office\ClickToRun\Configuration\AudienceData");
if (test == null)
{
using (var hklmTest32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
{
test = hklmTest32.GetValue(#"SOFTWARE\Microsoft\Office\ClickToRun\Configuration\AudienceData");
}
}
}
So I first fetch the registry key using the 64bit view, then if null I retry using the 32bit view.
Problem: test is always NULL.
Of course the key exists and I can see it using regedit:
Of course I first tried simple code that until now always worked for me, but doesn't work to fetch this key:
test = Registry.LocalMachine.GetValue(#"SOFTWARE\Microsoft\Office\ClickToRun\Configuration\AudienceData");
test = Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\ClickToRun\Configuration", "AudienceData", null);
And more strange thing, it's that I had exactly the same problem for fetching the windows build number. This code was not working :
var wBuild = Registry.LocalMachine.GetValue(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\ReleaseId");
But this one works perfectly for windows build (not for outlook key):
var wBuild = Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ReleaseId", null);
Any idea how to fetch this registry key ?
UPDATE 1
See the post C# get Office ClickToRun Registry Key returns null
But reading the post, my code using RegistryView.RegistryXX should work...
UPDATE 2
I've reprod the problem using LinqPad, so this is not due to the Outlook host / add-in. I tried to reprod in a .NET Fiddle but indeed the code is not allowed to access the registry :)
I can get the correct values using P/Invoke like explained in this article. So for me it's clearly a 32/64bit (wow6432node) problem.
you dont need
RegistryKey.OpenBaseKey
just use Registry.GetValue(keyName, valueName, defualt value)
this is working example
string InstallPath = (string)Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\" + path, "ActivationCode", null);
I can get the correct values using P/Invoke like explained in this article. So for me it's clearly a 32/64bit (wow6432node) problem.

32-bit Windows service writing to the 64-bit registry. (AutoAdminLogon Keys)

// Edit:
oh wow. It's odd that I've been working on this for a day now and just realized I needed to do:
key = key.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true);
And then everything worked. I did not know that you had to do that. Thanks for everyone that responded. I was just messing around and searched for my key and noticed it was being placed in the wrong spot.
// Original question:
I haven't seen a working solution for this and I'm not sure if it's a bug.
I have a C# 32-bit Windows service running on Windows 7 64-bit. My goal is to write to the 64-bit registry and not the Wow6432Node subkey since for AutoAdminLogon a 64-bit system doesn't seem to check the 32-bit view of the keys.
So my code is as follows:
static public void LoginAsGuest(EventLog eventLogger)
{
RegistrySecurity userSecurity = new RegistrySecurity();
RegistryAccessRule userRule = new RegistryAccessRule("Everyone", RegistryRights.FullControl, AccessControlType.Allow);
userSecurity.AddAccessRule(userRule);
var key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
key.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", RegistryKeyPermissionCheck.ReadWriteSubTree);
if (key == null)
{
eventLogger.WriteEntry("Error accessing the registry key");
}
else
{
try
{
key.SetValue("AutoAdminLogon", "1", RegistryValueKind.String);
key.SetValue("DefaultUserName", "guest", RegistryValueKind.String);
key.SetValue("DefaultPassword", "password", RegistryValueKind.String);
}
catch (Exception exception)
{
eventLogger.WriteEntry("Problem setting up keys: " + exception);
}
}
key.Close();
Reboot();
}
No exception or error is thrown. Nothing is written to the registry in the 32-bit or 64-bit view. I've tried using:
key.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true);
But it has the same outcome. Now if I just write without any view then my program successfully writes to the subkey:
SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Winlogon
Basically all I want is to write to the subkey:
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
Anyone know why the above code isn't writing to the requested key? (I will point out that AutoAdminLogon and the other two keys are used by the windows default credential provider such that when windows starts it checks those keys and if AutoAdminLogon is set to 1 then it logs in automatically with the given username and password. I'm doing this to allow a computer to be logged in as guest by setting the keys then rebooting the computer).
It's odd that I've been working on this for a day now and just realized I needed to do:
key = key.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true);
And then everything worked. I did not know that you had to do that. Thanks for everyone that responded. I was just messing around and searched for my key and noticed it was being placed in the wrong spot.

Writing to registry in a C# application

I'm trying to write to the registry using my C# app.
I'm using the answer given here: Writing values to the registry with C#
However for some reason the key isn't added to the registry.
I'm using the following code:
string Timestamp = DateTime.Now.ToString("dd-MM-yyyy");
string key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\"+Application.ProductName+"\\"+Application.ProductVersion;
string valueName = "Trial Period";
Microsoft.Win32.Registry.SetValue(key, valueName, Timestamp, Microsoft.Win32.RegistryValueKind.String);
The Application.name and Application.version 'folders' don't exists yet.
Do I have to create them first?
Also, I'm testing it on a 64b Win version so I think if I want to check the registry for the key added I have to specifically check the 32bit registry in: C:\Windows\SysWOW64\regedit.exe don't I?
First of all if you want to edit key under LocalMachine you must run your application under admin rights (better use CurrentUser it's safer or create the key in installer). You have to open key in edit mode too (OpenSubKey method) to add new subkeys. I've checked the code and it works. Here is the code.
RegistryKey key = Registry.LocalMachine.OpenSubKey("Software",true);
key.CreateSubKey("AppName");
key = key.OpenSubKey("AppName", true);
key.CreateSubKey("AppVersion");
key = key.OpenSubKey("AppVersion", true);
key.SetValue("yourkey", "yourvalue");
You can use the following code to create and open the required registry keys.
RegistryKey SoftwareKey = Registry.LocalMachine.OpenSubKey("Software",true);
RegistryKey AppNameKey = SoftwareKey.CreateSubKey("AppName");
RegistryKey AppVersionKey = AppNameKey.CreateSubKey("AppVersion");
AppVersionKey.SetValue("yourkey", "yourvalue");
You can basically use CreateSubKey for all your application settings, as it will open the key for write access, if it already exists, and create it otherwise. There is no need to create first, and then open. OpenSubKey comes in handy when you are absolutely certain the key already exists, like in this case, with "HKEY_LOCAL_MACHINE\SOFTWARE\"
Also check if your registry calls are getting virtualised. See here for more information.
It can happen if your application is not UAC aware and occurs for compatibility reasons.
Real path
HKEY_LOCAL_MACHINE\Software\FooKey
Virtual path
HKEY_USERS\<User SID>_Classes\VirtualStore\Machine\Software\FooKey
Try to open HKLM\Software first. Then create key for your program, and then create key for version. Howewer, your key could be placed at HKLM\software\WOW6432Node. Check this.
The problem is you don't have enough privileges. Here is a way that works for my:
RegistryKey myKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
myKey = myKey.OpenSubKey(subkey, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.FullControl);
if (myKey != null)
{
myKey.SetValue("DefaultPrinterId", ldiPrinters[e.RowIndex].id, RegistryValueKind.String);
myKey.Close();
}
With RegistryKey.OpenBaseKey you open the correct registry, because when you don't have permissions the registry that you write, it does in another location.
By default, your changes will be written to HKLM\SOFTWARE\WOW6432Node\... because of registry redirection. This can be quite confusing.
In order to write to HKLM\SOFTWARE\..., you need to use RegistryKey.OpenBaseKey to open the 64-bit registry:
var path = #"SOFTWARE\...";
var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
var key = baseKey.CreateSubKey(path, RegistryKeyPermissionCheck.ReadWriteSubTree);
key.SetValue(name, value, RegistryValueKind.String);
Also, you need to have permission to write to the specified registry key.
You can get permission either by assigning permissions to specific users or service accounts or by running your app in elevated mode.

Categories

Resources