Get value from a registry key string - c#

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).

Related

Registry Key Mapping

I am building an application in which I need to be able to gather information from the user's local Registry, and then utilize that to perform various tasks. I know where the certain registry key is located, but I can't seem to figure out how to properly extract the data. Here is the one I am trying to extract:
My ideal event would happen as follows: the utility searches for the registry value, determines it and stores it (in a var or something), then a button is displayed to the user to proceed to the next screen (I'm using WinForms). I have already set the button as "invisible" beforehand. See the attached code.
using (RegistryKey key = Registry.LocalMachine.OpenSubKey("HKEY_LOCAL_MACHINE\Software\Wow6432Node\DovetailGames\FSX\10.0"))
{
if (key != null)
{
Object o = key.GetValue("Install_Path");
if (o != null)
{
sc3op2.Visible = true; //Button is "sc3op2"
}
}
}
I guess my main problem is the formatting of the code to extract these values. Any help would be appreciated. Thanks.
Your answer might be here. Apparently, it has something to do with the virtualization of the application settings for 32 and 64-bit platforms. See the updated section If it returns null, set your build architecture to Any CPU. On my 64-bit platform, I am getting null when built using x86 or Any CPU build configuration. But it is returning the value when built using x64.
const string keyName = #"Software\Wow6432Node\DovetailGames\FSX";
var o = Registry.LocalMachine.OpenSubKey(keyName, false);
var value = o?.GetValue("Install_Path", "-");
Console.WriteLine(value);
First you need to remove HKEY_LOCAL_MACHINE.
You need to use # before the string.
take a look Screenshot
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Apple Inc.\Apple Application Support"))
{
if (key != null)
{
Object o = key.GetValue("Installdir");
if (o != null)
{
// do something
}
}
}

Reading a value from registry C#

I am trying to read the recent
this is the code i have right now:
RegistryKey registryKey = Registry.CurrentUser.OpenSubKey(#"Software\Microsoft\Visual Studio\12.0\ProjectMRUList");
string data2 = (string)registryKey.GetValue("File1".ToUpper());
recentProjects.Items.Add(data2);
i keep getting a null error.
System.NullReferenceException: Object reference not set to an instance
of an object.
The error is on
string data2 = (string)registryKey.GetValue("File1");
The subkey is actually "VisualStudio", not "Visual Studio". Try the below:
RegistryKey registryKey = Registry.CurrentUser.OpenSubKey(#"Software\Microsoft\VisualStudio\12.0\ProjectMRUList");
string data2 = (string)registryKey.GetValue("File1".ToUpper());
Or better still, you can have control over whether the environment is 32 or 64 bit, for example...
using (var hklm = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64))
{
using (var key = hklm.OpenSubKey(#"Software\Microsoft\VisualStudio\12.0\ProjectMRUList"))
{
string data2 = (string)key.GetValue("File1".ToUpper());
}
}

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

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.

How to search for specific value in Registry keys

How can I search for specific value in the registry keys?
For example I want to search for XXX in
HKEY_CLASSES_ROOT\Installer\Products
any code sample in C# will be appreciated,
thanks
In case you don't want to take a dependency on LogParser (as powerful as it is): I would take a look at the Microsoft.Win32.RegistryKey class (MSDN). Use OpenSubKey to open up HKEY_CLASSES_ROOT\Installer\Products, and then call GetSubKeyNames to, well, get the names of the subkeys.
Open up each of those in turn, call GetValue for the value you're interested in (ProductName, I guess) and compare the result to what you're looking for.
Help here...
Microsoft has a great (but not well known) tool for this - called LogParser
It uses a SQL engine to query all kind of text based data like the Registry,
the Filesystem, the eventlog, AD etc...
To be usable from C#, you need to build an Interop Assembly from the
Logparser.dll COM server using following (adjust LogParser.dll path)
command.
tlbimp "C:\Program Files\Log Parser 2.2\LogParser.dll"
/out:Interop.MSUtil.dll
Following is a small sample, that illustrates how to query for the Value
'VisualStudio' in the \HKLM\SOFTWARE\Microsoft tree.
using System;
using System.Runtime.InteropServices;
using LogQuery = Interop.MSUtil.LogQueryClass;
using RegistryInputFormat = Interop.MSUtil.COMRegistryInputContextClass;
using RegRecordSet = Interop.MSUtil.ILogRecordset;
class Program
{
public static void Main()
{
RegRecordSet rs = null;
try
{
LogQuery qry = new LogQuery();
RegistryInputFormat registryFormat = new RegistryInputFormat();
string query = #"SELECT Path from \HKLM\SOFTWARE\Microsoft where
Value='VisualStudio'";
rs = qry.Execute(query, registryFormat);
for(; !rs.atEnd(); rs.moveNext())
Console.WriteLine(rs.getRecord().toNativeString(","));
}
finally
{
rs.close();
}
}
}
This method will search a specified registry key for the first subkey that contains a specified value. If the key is found then the specified value is returned. Searchign is only one level deep. If you require deeper searching then I suggest modifying this code to make use of recursion. Searching is case-sensitive but again you can modify that if required.
private string SearchKey(string keyname, string data, string valueToFind, string returnValue)
{
RegistryKey uninstallKey = Registry.LocalMachine.OpenSubKey(keyname);
var programs = uninstallKey.GetSubKeyNames();
foreach (var program in programs)
{
RegistryKey subkey = uninstallKey.OpenSubKey(program);
if (string.Equals(valueToFind, subkey.GetValue(data, string.Empty).ToString(), StringComparison.CurrentCulture))
{
return subkey.GetValue(returnValue).ToString();
}
}
return string.Empty;
}
Example usage
// This code will find the version of Chrome (32 bit) installed
string version = this.SearchKey("SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall", "DisplayName", "Google Chrome", "DisplayVersion");
#Caltor your solution gave me the answer I was looking for. I welcome improvements or a completely different solution that does not involve the registry. I am working with enterprise applications on Windows 10 with devices joined to Azure AD. I want/need to use Windows Hello for devices and for HoloLens 2 in a UWP app. My problem has been getting the AAD userPrincipal name from Windows 10. After a couple days searching and trying lots of code I searched the Windows Registry for my AAD account in the Current User key and found it. With some research it appears that this information is in a specific key. Because you can be joined to multiple directories there may be more than one entry. I was not trying to solve that issue, that is done with the AAD tenant Id. I just needed the AAD userPrincipal name.
My solution de-dups the return list so that I have a list of unique userPrincipal names. App users may have to select an account, this is tolerable for even HoloLens.
using Microsoft.Win32;
using System.Collections.Generic;
using System.Linq;
namespace WinReg
{
public class WinRegistryUserFind
{
// Windows 10 apparently places Office/Azure AAD in the registry at this location
// each login gets a unique key in the registry that ends with the aadrm.com and the values
// are held in a key named Identities and the value we want is the Email data item.
const string regKeyPath = "SOFTWARE\\Classes\\Local Settings\\Software\\Microsoft\\MSIPC";
const string matchOnEnd = "aadrm.com";
const string matchKey = "Identities";
const string matchData = "Email";
public static List<string> GetAADuserFromRegistry()
{
var usersFound = new List<string>();
RegistryKey regKey = Registry.CurrentUser.OpenSubKey(regKeyPath);
var programs = regKey.GetSubKeyNames();
foreach (var program in programs)
{
RegistryKey subkey = regKey.OpenSubKey(program);
if(subkey.Name.EndsWith(matchOnEnd))
{
var value = (subkey.OpenSubKey(matchKey) != null)? (string)subkey.OpenSubKey(matchKey).GetValue(matchData): string.Empty;
if (string.IsNullOrEmpty(value)) continue;
if((from user in usersFound where user == value select user).FirstOrDefault() == null)
usersFound.Add(value) ;
}
}
return usersFound;
}
}
}

Categories