【问题标题】:Registry.LocalMachine.OpenSubKey(regPath); returns NULL in .NET 3.5 EnvironmentRegistry.LocalMachine.OpenSubKey(regPath);在 .NET 3.5 环境中返回 NULL
【发布时间】:2015-08-03 06:36:12
【问题描述】:

我正在尝试使用以下命令访问注册表:

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

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

我也尝试了不同的方法,即this onethis,但我遇到了同样的错误:

对象引用未设置为对象的实例。

它总是在ribbonKey 中返回 null,但是注册表中存在密钥。我已经搜索了这个主题并找到了很多解决方案,但即使是 this 也无法帮助我,因为我正在使用 .NET 3.5

我们将不胜感激。

【问题讨论】:

  • 好的,我已经创建了一个具有相同路径的密钥,并在使用 .NET 3.5 的控制台应用程序中测试了这两行,它工作正常......
  • 那么我这边可能出现的问题是什么?
  • 你运行的是什么系统?我已经在 Windows 8.1 机器上测试了我的
  • Windows 8.1 企业版,64 位操作系统
  • 所以,我认为这个页面会对您有所帮助:rhyous.com/2011/01/24/… 我将我的应用程序构建为 32 位应用程序,但我遇到了同样的问题。

标签: c# .net windows registry


【解决方案1】:

您正在运行什么系统?必须尝试这个小解决方案吗?

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

【讨论】:

    【解决方案2】:

    这可能是因为注册表有不同的 x32 和 x64 键。使用 3.5 框架对您来说重要吗? 如果没有 - 您可以将其更改为 4.0 并使用此代码:

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

    如果 3.5 框架对您很重要 - 您应该使用一些技巧。我在这里找到了它: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;
        }
    }
    

    使用示例:

    var key64 = RegistryExtensions.OpenBaseKey(RegistryHive.LocalMachine, RegistryExtensions.RegistryHiveType.X64);
    var keyPath = @"Software\\Bentley\\AutoPIPE\\V8i Ribbon and Reporting";
    var key = key64.OpenSubKey(keyPath);
    

    【讨论】:

    • 非常感谢您的回复,但它会引发异常。错误消息是Access is denied。需要更多帮助来解决问题
    • 你能告诉我,你到底在哪里得到了错误信息?
    • int result = RegOpenKeyEx(hiveKey, String.Empty, 0, (uint)flags, out keyHandlePointer); 在结果中得到5 因此结果既不是0 也不是2 所以throw new Win32Exception(result);else-if 条件被跳过之后执行。如何授予程序适当的权限?
    • 好的,我有另一个变种。请更改此标志:RegistryAccessMask flags = RegistryAccessMask.QueryValue | RegistryAccessMask.EnumerateSubKeys | RegistryAccessMask.Read;
    • 我以管理员身份登录。你能详细说明一下UAC这个词吗?
    猜你喜欢
    • 1970-01-01
    • 2014-11-29
    • 2020-01-02
    • 1970-01-01
    • 2021-05-14
    • 2018-09-30
    • 1970-01-01
    • 2016-11-11
    • 1970-01-01
    相关资源
    最近更新 更多