Dmitriy Kudinov
Dmitriy Kudinov

Reputation: 1072

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.

Upvotes: 9

Views: 25524

Answers (6)

Gerald Hughes
Gerald Hughes

Reputation: 6157

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

Upvotes: 0

JustASingleBit
JustASingleBit

Reputation: 24

I solved the problem when i imported Microsoft.Win32 and changed the application-settings to x64 like pedrocgsousa mentioned.

Upvotes: -1

Mark Sowul
Mark Sowul

Reputation: 10610

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.

Upvotes: 7

pedrocgsousa
pedrocgsousa

Reputation: 417

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.

Upvotes: 23

Ken White
Ken White

Reputation: 125748

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.

Upvotes: 3

Aidiakapi
Aidiakapi

Reputation: 6249

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.

Upvotes: 7

Related Questions