Reading registry value crashes - c#

My below code fails no matter if I run it as Administrator or not:
var suff = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\CCM\\LocationServices", true);
var value = suff.GetValue("DnsSuffix").ToString();
I get this error message which I can't decode:
An unhandled exception of type 'System.NullReferenceException' occurred in MyApp.exe Additional information: Object reference not set to an instance of an object.
I know for a fact that the value exists and it contains data as well.
*Edit: So like I said it shouldn't be null as the data exists. And if it is null then I will need to know why is it null. Therefore, a question regarding what is System.NullReferenceException won't help me at all.

As raj's answer pointed out in this SO question, which is similar to yours, the problem could be that you're opening the registry on a 64bits OS.
Try this approach instead (.NET 4.0 or later) :
public class HKLMRegistryHelper
{
public static RegistryKey GetRegistryKey()
{
return GetRegistryKey(null);
}
public static RegistryKey GetRegistryKey(string keyPath)
{
RegistryKey localMachineRegistry = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32);
return string.IsNullOrEmpty(keyPath) ? localMachineRegistry : localMachineRegistry.OpenSubKey(keyPath);
}
public static object GetRegistryValue(string keyPath, string keyName)
{
RegistryKey registry = GetRegistryKey(keyPath);
return registry.GetValue(keyName);
}
}
... and replace your code with :
string keyPath = #"SOFTWARE\Microsoft\CCM\LocationServices";
string keyName = "DnsSuffix";
var value = HKLMRegistryHelper.GetRegistryValue(keyPath, keyName);

Reading the registry with "Registry.LocalMachine" can be unreliable as it defaults to the current application platform target (x86/x64) and when it's 64bit Registry.LocalMachine can view the key but can't access the data within.
Try specifying the view with RegistryKey.
var stuff = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)
.OpenSubKey("Software\\Microsoft\\CCM\\LocationServices", true);
var value = stuff.GetValue("DnsSuffix").ToString();

Related

Get value from a registry key string

I am trying got do a simple read of a registry key but I cannot make it work even after reading many posts. What am I missing? I am running VS2015 as Administrator.
Exporting the key it is as follows
[HKEY_LOCAL_MACHINE\SOFTWARE\Test Key\dev]
"Enable"="TRUE"
I try to read it as follows
string myVal = (string)Registry.LocalMachine.GetValue(#"SOFTWARE\Test Key\dev\Enable");
MessageBox.Show(myVal);
I also tried (and variations)
RegistryKey key = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Test Key\dev");
string myVal = (string)key.GetValue("Enable");
MessageBox.Show(myVal);
I always get back NULL, why?
Are you on a 64 bits environment?
If so, try to set up the RegistryView parameter to make sure you access the 64 bit version of the registry:
using (var root = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
{
using (var key = root.OpenSubKey(#"SOFTWARE\Test Key\dev", false))
{
var myVal= key.GetValue("Enable");
MessageBox.Show(myVal.ToString());
}
}
If still doesn't work, try with RegistryView.Registry32 instead.
EDIT
You can actually set RegistryView dynamically using Environment.Is64BitOperatingSystem:
using (var root = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
Environment.Is64BitOperatingSystem
? RegistryView.Registry64
: RegistryView.Registry32))
{
using (var key = root.OpenSubKey(#"SOFTWARE\Test Key\dev", false))
{
var myVal= key.GetValue("Enable");
MessageBox.Show(myVal.ToString());
}
}
This will only work if the registry entry exists for the current platform (It could happen that it was just saved in the 32 bit version of the registry).

Find and Read registry key within CLR

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();

Retrieving file installation path from registry

I am creating a WPF utility which needs to access the registry of the local machine, to then find out the installation path of the program.
I've navigated to the key via Regedit and it gives a Name, Type and Data, within the Data it shows the installation path, I would like to extract the installation path.
I know I need to navigate to this key within the registry:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\
then I need to access a folder within this key with the information regarding the installation path.
-
I solved my problem, to anyone who wants a solution in the future if your still stuck after this please message me, I found it was hard to find the resources.
RegistryKey key = Registry.LocalMachine.OpenSubKey(#"Software\Microsoft\Windows\CurrentVersion\App Paths\myexe.exe");
string regFilePath = null;
object objRegisteredValue = key.GetValue("");
registeredFilePath = value.ToString();
To read registry keys you should use Microsot.Windows.RegistryKey class, class Registry can open for you the RegistryKey.
This question was very helpful to me. I came up with a helper class, wanting to play with the new Tuples.
Example usage:
public string SkypeExePath => InstalledApplicationPaths.GetInstalledApplicationPath( "lync.exe" );
The class:
public static class InstalledApplicationPaths
{
public static string GetInstalledApplicationPath( string shortName )
{
var path = GetInstalledApplicationPaths().SingleOrDefault( x => x?.ExectuableName.ToLower() == shortName.ToLower() )?.Path;
return path;
}
public static IEnumerable<(string ExectuableName, string Path)?> GetInstalledApplicationPaths()
{
using ( RegistryKey key = Registry.LocalMachine.OpenSubKey( #"Software\Microsoft\Windows\CurrentVersion\App Paths" ) )
{
foreach ( var subkeyName in key.GetSubKeyNames() )
{
using ( RegistryKey subkey = key.OpenSubKey( subkeyName ) )
{
yield return (subkeyName, subkey.GetValue( "" )?.ToString());
}
}
}
}
}

What's wrong with Registry.GetValue?

I trying to get a registry value:
var value = Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography", "MachineGuid", 0);
In Windows XP all ok, but in Windows 7 returns 0. In HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography using regedit I see MachineGuid, but if I run
var keys = Registry.LocalMachine.OpenSubKey("SOFTWARE").OpenSubKey("Microsoft").OpenSubKey("Cryptography", RegistryKeyPermissionCheck.ReadSubTree).GetValueNames();
keys.Length is 0.
What do I do wrong? With other values all ok in both of OS.
The problem is that you probably are compiling the solution as x86, if you compile as x64 you can read the values.
Try the following code compiling as x86 and x64:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("MachineGUID:" + MachineGUID);
Console.ReadKey();
}
public static string MachineGUID
{
get
{
Guid guidMachineGUID;
if (Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Cryptography") != null)
{
if (Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Cryptography").GetValue("MachineGuid") != null)
{
guidMachineGUID = new Guid(Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Cryptography").GetValue("MachineGuid").ToString());
return guidMachineGUID.ToString();
}
}
return null;
}
}
}
You can read more about Accessing an Alternate Registry View.
You can found in here a way of reading values in x86 and x64.
It probably has to do with UAC (User Account Control). The extra layer of protection for Windows Vista and Windows 7.
You'll need to request permissions to the registry.
EDIT:
Your code right now:
var keys = Registry.LocalMachine.OpenSubKey("SOFTWARE")
.OpenSubKey("Microsoft")
.OpenSubKey("Cryptography", RegistryKeyPermissionCheck.ReadSubTree)
.GetValueNames();
Only requests the permissions on the Cryptography subkey, maybe that causes the problem (at least I had that once), so the new code would then be:
var keys = Registry.LocalMachine.OpenSubKey("SOFTWARE", RegistryKeyPermissionCheck.ReadSubTree)
.OpenSubKey("Microsoft", RegistryKeyPermissionCheck.ReadSubTree)
.OpenSubKey("Cryptography", RegistryKeyPermissionCheck.ReadSubTree)
.GetValueNames();
EDIT2:
I attached the debugger to it, on this code:
var key1 = Registry.LocalMachine.OpenSubKey("SOFTWARE", RegistryKeyPermissionCheck.ReadSubTree);
var key2 = key1.OpenSubKey("Microsoft", RegistryKeyPermissionCheck.ReadSubTree);
var key3 = key2.OpenSubKey("Cryptography", RegistryKeyPermissionCheck.ReadSubTree);
var key4 = key3.GetValueNames();
It turns out, you can read that specific value, at least that's my guess, because all data is correct, until I open key3, there the ValueCount is zero, instead of the expected 1.
I think it's a special value that's protected.
You say you're on 64-bit Windows: is your app 32-bit? If so it's probably being affected by registry redirection and is looking at HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography. You may have to P/Invoke to work around it: http://msdn.microsoft.com/en-us/library/aa384129.aspx.
If you're not an administrator, you only have read permission on HKLM. You need to open the key read-only instead. Not sure how to do that with .NET's Registry class; with the API directly, you use RegOpenKeyEx() with the KEY_READ flag.
EDIT: After checking MSDN, I see that OpenSubKey() does open read only, and returns the contents if it succeeds and nothing if it fails. Since you're chaining multiple OpenSubKey calls, it's most likely one of them that's failing that causes the others to fail. Try breaking them out into separate calls, and checking the intermediate values returned.
Maybe a little late to the party, but, none of the solutions worked for me.
This is how I've solved this issue:
public static Guid GetMachineGuid
{
get
{
var machineGuid = Guid.Empty;
var localMachineX64View = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
var cryptographySubKey = localMachineX64View.OpenSubKey(#"SOFTWARE\Microsoft\Cryptography");
if (cryptographySubKey == null) return machineGuid;
var machineGuidValue = (string)cryptographySubKey.GetValue("MachineGuid");
Guid.TryParse(machineGuidValue, out machineGuid);
return machineGuid;
}
}
I solved the problem when i imported Microsoft.Win32 and changed the application-settings to x64 like pedrocgsousa mentioned.

Access remote registry key with C# in .Net MVC2

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();
}

Categories