0

I am trying to access the Registry using the following command:

string regPath = "Software\\Bentley\\AutoPIPE\\V8i Ribbon and Reporting";

RegistryKey ribbonKey = Registry.LocalMachine.OpenSubKey(regPath);

I have tried different methods i.e. this one and this too but I faced the same error:

Object reference not set to an instance of an Object.

It always return me null in the ribbonKey however the key exists in the registry. I have searched on this topic and found many solutions but even this could not help me because I am using .NET 3.5.

Any help will be highly appreciated.

Community
  • 1
  • 1
Itban Saeed
  • 1,660
  • 5
  • 25
  • 38
  • OK, I've created a Key with the same path and tested those two lines in a console application with .NET 3.5 and it worked ... – tinu Aug 03 '15 at 06:46
  • so what can be the possible issue on my side? – Itban Saeed Aug 03 '15 at 06:47
  • What system are you running? I've tested mine on a Windows 8.1 machine – tinu Aug 03 '15 at 06:54
  • Windows 8.1 Enterprise, 64-bit Operating System – Itban Saeed Aug 03 '15 at 06:57
  • 1
    So, I think this page will help you: http://www.rhyous.com/2011/01/24/how-read-the-64-bit-registry-from-a-32-bit-application-or-vice-versa/ I built my app as a 32-bit application and I got the same issue. – tinu Aug 03 '15 at 07:05
  • Thanks a lot but I have already checked it, `.NET 3.5 SP1 and Prior` does not work for me. It also returns null in `value32` – Itban Saeed Aug 03 '15 at 07:08

2 Answers2

1

What System are you running? Have to tried this little solution?

OpenSubKey() returns null for a registry key that I can see in regedit.exe

Community
  • 1
  • 1
Jan Unld
  • 370
  • 1
  • 10
1

It can be because registry has different keys for x32 and x64. Is it important for you to use 3.5 framework? If no - you can change it to 4.0 and use this code:

var regView = Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32;
var registry = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, regView);

var keyPath = @"Software\\Bentley\\AutoPIPE\\V8i Ribbon and Reporting";
var key = registry.OpenSubKey(keyPath);

If 3.5 framework important for you - you should use some trick. I found it here: What are some alternatives to RegistryKey.OpenBaseKey in .NET 3.5?

public static class RegistryExtensions
{

    public enum RegistryHiveType
    {
        X86,
        X64
    }

    static Dictionary<RegistryHive, UIntPtr> _hiveKeys = new Dictionary<RegistryHive, UIntPtr> 
    {
        { RegistryHive.ClassesRoot, new UIntPtr(0x80000000u) },
        { RegistryHive.CurrentConfig, new UIntPtr(0x80000005u) },
        { RegistryHive.CurrentUser, new UIntPtr(0x80000001u) },
        { RegistryHive.DynData, new UIntPtr(0x80000006u) },
        { RegistryHive.LocalMachine, new UIntPtr(0x80000002u) },
        { RegistryHive.PerformanceData, new UIntPtr(0x80000004u) },
        { RegistryHive.Users, new UIntPtr(0x80000003u) }
    };

    static Dictionary<RegistryHiveType, RegistryAccessMask> _accessMasks = new Dictionary<RegistryHiveType, RegistryAccessMask> 
    {
        { RegistryHiveType.X64, RegistryAccessMask.Wow6464 },
        { RegistryHiveType.X86, RegistryAccessMask.WoW6432 }
    };

    [Flags]
    public enum RegistryAccessMask
    {
        QueryValue          = 0x0001,
        SetValue            = 0x0002,
        CreateSubKey        = 0x0004,
        EnumerateSubKeys    = 0x0008,
        Notify              = 0x0010,
        CreateLink          = 0x0020,
        WoW6432             = 0x0200,
        Wow6464             = 0x0100,
        Write               = 0x20006,
        Read                = 0x20019,
        Execute             = 0x20019,
        AllAccess           = 0xF003F
    }

    [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
    public static extern int RegOpenKeyEx
    (
      UIntPtr hKey,
      string subKey,
      uint ulOptions,
      uint samDesired,
      out IntPtr hkResult
    );

      public static RegistryKey OpenBaseKey(RegistryHive registryHive, RegistryHiveType registryType)
    {
        int result = -1;
        UIntPtr hiveKey = _hiveKeys[registryHive];
        if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major > 5)
        {
            RegistryAccessMask flags = RegistryAccessMask.QueryValue | RegistryAccessMask.EnumerateSubKeys | RegistryAccessMask.Read;
            IntPtr keyHandlePointer = IntPtr.Zero;
            result = RegOpenKeyEx(hiveKey, String.Empty, 0, (uint) flags, out keyHandlePointer);
            if (result == 0)
            {
                var safeRegistryHandleType = typeof (SafeHandleZeroOrMinusOneIsInvalid).Assembly.GetType("Microsoft.Win32.SafeHandles.SafeRegistryHandle");
                var safeRegistryHandleConstructor = safeRegistryHandleType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] {typeof (IntPtr), typeof (bool)}, null); // .NET < 4
                if (safeRegistryHandleConstructor == null)
                    safeRegistryHandleConstructor = safeRegistryHandleType.GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, new[] {typeof (IntPtr), typeof (bool)}, null); // .NET >= 4
                var keyHandle = safeRegistryHandleConstructor.Invoke(new object[] {keyHandlePointer, true});
                var net3Constructor = typeof (RegistryKey).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] {safeRegistryHandleType, typeof (bool)}, null);
                var net4Constructor = typeof (RegistryKey).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] {typeof (IntPtr), typeof (bool), typeof (bool), typeof (bool), typeof (bool)}, null);
                object key;
                if (net4Constructor != null)
                    key = net4Constructor.Invoke(new object[] {keyHandlePointer, true, false, false, hiveKey == _hiveKeys[RegistryHive.PerformanceData]});
                else if (net3Constructor != null)
                    key = net3Constructor.Invoke(new object[] {keyHandle, true});
                else
                {
                    var keyFromHandleMethod = typeof (RegistryKey).GetMethod("FromHandle", BindingFlags.Static | BindingFlags.Public, null, new[] {safeRegistryHandleType}, null);
                    key = keyFromHandleMethod.Invoke(null, new object[] {keyHandlePointer});
                }
                var field = typeof (RegistryKey).GetField("keyName", BindingFlags.Instance | BindingFlags.NonPublic);
                if (field != null)
                    field.SetValue(key, String.Empty);
                return (RegistryKey) key;
            }
            else if (result == 2) // The key does not exist.
                return null;
            throw new Win32Exception(result);
        }
        return null;
    }
}

Example of usage:

var key64 = RegistryExtensions.OpenBaseKey(RegistryHive.LocalMachine, RegistryExtensions.RegistryHiveType.X64);
var keyPath = @"Software\\Bentley\\AutoPIPE\\V8i Ribbon and Reporting";
var key = key64.OpenSubKey(keyPath);
Community
  • 1
  • 1
Artem Kulikov
  • 2,250
  • 19
  • 32
  • Thanks a lot for the response but it throws an exception. Error message is `Access is denied`. Some more help is needed to solve the problem – Itban Saeed Aug 03 '15 at 09:35
  • Can you tell me, where exactly you got error message? – Artem Kulikov Aug 03 '15 at 09:39
  • `int result = RegOpenKeyEx(hiveKey, String.Empty, 0, (uint)flags, out keyHandlePointer);` gets `5` in result hence the result is neither `0` nor `2` so `throw new Win32Exception(result);` is executed after `else-if` condition is skipped. How can I grant appropriate permissions to the program? – Itban Saeed Aug 03 '15 at 09:43
  • Okay, I have another variant. Please change flags on this: RegistryAccessMask flags = RegistryAccessMask.QueryValue | RegistryAccessMask.EnumerateSubKeys | RegistryAccessMask.Read; – Artem Kulikov Aug 03 '15 at 09:47
  • I am logged in as an administrator. Can you please elaborate the term `UAC`? – Itban Saeed Aug 03 '15 at 09:51
  • Actually it was bad idea. It's not necessary to user to have administrator privileges. I updated the code in answer, check it please. I change some flags for accessing to registry. Hope it helps.. – Artem Kulikov Aug 03 '15 at 09:52
  • After fixing two errors, I got these two: `The name 'safeRegistryHandleType' does not exist in the current context` `The name 'key' does not exist in the current context` please tell me if `safeRegistryHandleType` requires any namespace. – Itban Saeed Aug 03 '15 at 10:03
  • It's just a "System.Type". Can you share your code? it looks like you just forgot some bracket { or } ... – Artem Kulikov Aug 03 '15 at 10:26
  • Please, be careful with brackets. When you updated code - you changed their positions. I update my answer with your code (changed function "OpenBaseKey") – Artem Kulikov Aug 03 '15 at 10:38
  • Thanks a lot, the code compiled successfully now please tell me where to add the `keyPath` and the `attribute` name to get the value. – Itban Saeed Aug 03 '15 at 10:48
  • In the end of my answer, example of usage. – Artem Kulikov Aug 03 '15 at 10:53
  • So after all the efforts the final result in the variable `key` is again null. – Itban Saeed Aug 03 '15 at 10:56
  • Don't be upset, we'll finish it :) First of all, try to use keypath: "var keyPath = @"Software\\"; It should return you not null key. IS it? – Artem Kulikov Aug 03 '15 at 10:59
  • It returns "\Software" – Itban Saeed Aug 03 '15 at 11:01
  • So, code works good. Are you sure that you have registry key, that you tried to get? Please open "regedit" and make sure, that you can find necessary key.. – Artem Kulikov Aug 03 '15 at 11:02
  • Ensuring the existence of path was my first step after facing the error. Code works even if the path is @"Software\\Bentley\\" but when I change the path to @"Software\\Bentley\\AutoPIPE\\" it returns null – Itban Saeed Aug 03 '15 at 11:06
  • Can you export path to this key from regedit (open regedit, find your key. press right mouse button and export)? – Artem Kulikov Aug 03 '15 at 11:15
  • It does not give the option of importing. There are only four options: modify, modify binary data, delete and rename. – Itban Saeed Aug 03 '15 at 11:34
  • Looks like that AutoPipe is a value, not a registry key :) If yes - you should work with it this: var keyPath = @"Software\\Bentley\"; var key = key64.OpenSubKey(keyPath); var value = key.GetValue("AUTOPipe"); – Artem Kulikov Aug 03 '15 at 11:38
  • In this case `object objRegisteredValue = ribbonKey.GetValue("AutoPipe");` receives null :) – Itban Saeed Aug 03 '15 at 11:40
  • Can you send a printscreen from you regedit and opened key? I can't analize without it :) – Artem Kulikov Aug 03 '15 at 11:48
  • Kindly continue the discussion [chat](http://chat.stackoverflow.com/rooms/85002/discussion-between-itban-saeed-and-artem-kulikov) I have uploaded the screenshot there. – Itban Saeed Aug 03 '15 at 11:49