【问题标题】:NullReferenceException when opening a subkey I know exists打开我知道存在的子项时出现 NullReferenceException
【发布时间】:2018-07-07 14:38:16
【问题描述】:

我正在尝试打开一个注册表项,以便删除它的子项:

Dim asu As New System.Security.Principal.NTAccount(username.Text)
Dim si As System.Security.Principal.SecurityIdentifier = asu.Translate(GetType(System.Security.Principal.SecurityIdentifier))

Dim MyReg As Microsoft.Win32.RegistryKey
MyReg = Microsoft.Win32.RegistryKey.OpenRemoteBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, host.Text) _
    .OpenSubKey("Software\Microsoft\Windows NT\currentVersion\ProfileList\" & si.ToString & "\")

Dim myval As String
myval = MyReg.GetValue("Guid")
MsgBox(myval.ToString) ' retuns GUID no errors

Dim guid As String
guid = myval

Dim MyReg2 As Microsoft.Win32.RegistryKey
MyReg2 = Microsoft.Win32.RegistryKey.OpenRemoteBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, host.Text) _
    .OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileGuid\")

MsgBox(MyReg2.ToString)
'myreg2.DeleteSubKey(guid)

现在我已经测试了同一级别的其他键:

  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileNotification

它们都返回值,但在尝试打开 ProfileGuid 时会抛出 NullReferenceException。我可以完全访问远程注册表,并且我还在本地对其进行了测试,结果相同。我知道密钥存在。

有什么方法可以直接删除它而不打开子键?或者任何人都可以解释为什么它返回 null?

【问题讨论】:

  • ive 还尝试循环遍历顶层 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ code Dim SubKeyNames() As String = MyReg2.GetSubKeyNames() For Each s As String In SubKeyNames MsgBox (s.ToString)接下来code 我还给了“每个人”对密钥的完全访问权限,但仍然没有返回任何内容

标签: vb.net visual-studio-2013 registry nullreferenceexception


【解决方案1】:

您很可能遇到所谓的Registry Redirection

为了保持与 32 位应用程序的兼容性,64 位版本的 Windows 实现了 File System Redirector注册表重定向器。这两个的目的是保留一组单独的文件和注册表项(通常以 WOW64 为名),这些文件和注册表项仅特定于 32 位应用程序。

例如,由于 64 位进程无法加载 32 位代码,因此会保留一个单独的系统目录,其中仅包含 32 位版本的系统 DLL 和应用程序。 32位系统目录的路径是%SystemRoot%\SysWOW64,而64位的目录是标准的%SystemRoot%\System32

这在注册表中的工作方式相同,但只有一组特定的键具有各自的 32 位键。 32 位密钥始终作为标准 64 位密钥(例如HKLM\SOFTWARE)的子密钥定位,称为Wow6432Node

文件系统重定向器(以及相应的注册表重定向器)自动重定向所有 32 位应用程序到相应的 32 位目录/注册表项,以确保 32 位应用程序仍然可以在 64-位系统。默认情况下,Visual Studio 项目只针对 32 位

据我所知,有两种方法可以解决这个问题:

  1. 将您的应用编译为 AnyCPU 而不是 x86

    这是迄今为止最简单的解决方案。通过这样做,应用程序将自动在 32 位系统上作为 32 位应用程序运行,或在 64 位系统上作为 64 位应用程序运行。因此注册表重定向器不需要干预。

  2. 指定是要访问注册表的 32 位视图还是 64 位视图。

    .NET Framework 有一个内置功能,可让您指定是要访问注册表的 32 位视图还是 64 位视图。将其与 Environment.Is64BitOperatingSystem 结合以确定您要访问的视图。

    本地解决方案(供其他人看到):

    'Determine which registry view to use.
    Dim RegView As RegistryView = If(Environment.Is64BitOperatingSystem, RegistryView.Registry64, RegistryView.Registry32)
    
    'Opens HKEY_LOCAL_MACHINE with the specified registry view.
    Using RegHive As RegistryKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegView)
    
        'Open the "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileGuid" key.
        Using RegKey As RegistryKey = RegHive.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileGuid", True)
            'Do stuff with the registry key...
        End Using
    End Using
    

    远程解决方案:

    (与上面相同,但更改了Using RegHive As RegistryKey 行)

    Using RegHive As RegistryKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, host.txt, RegView)
    

【讨论】:

  • 非常感谢 - 奇怪的是我已经将它设置为编译到 AnyCPU 但你发布的第二种方法效果很好,谢谢。
  • @RobbieHoskins:很高兴我能帮上忙!编码愉快!
  • @RobbieHoskins :AnyCPU 没有自动工作的原因可能是因为您检查了Prefer 32-bit。有关更多信息,请参见:stackoverflow.com/q/12066638
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-16
  • 1970-01-01
  • 2017-10-16
  • 1970-01-01
  • 2014-12-24
  • 2012-10-25
相关资源
最近更新 更多