Access 64-bit key in Windows Registry through 32-bit application

I need to get information about the network to list in an application that I am doing, but I am having a problem accessing the Windows registry because of the project preference.

Path: right - click on the Class, click Properties, and then click compiler.

Note that below the CPU Target Field, there is a CheckBox (Prefer 32-bit)

If this option is ticked my code does not work in 64-bit system, but if I disable my application does not work on the 32-bit machine. If I comment all the procedures that look for values in regedit, the application works on both.

I would like to know if I can access the registry key in both 64bits and 32 bits.

Follows the Code:

  Public Sub ObterTipoDaRede(ByVal NomeConfiguracao As String, ByVal  _
 NomeConfiguracaoDois As String)
    Dim NomeDaRede As String
    Dim regKey
    Dim lDatas As New List(Of KeyValuePair(Of String, DateTime))

    'If Environment.Is64BitOperatingSystem Then

    'Else
    regKey = My.Computer.Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles")
    'End If

    Try
        For Each SubK In regKey.GetSubKeyNames

            Dim value = My.Computer.Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles\" + SubK)
            Dim data = My.Computer.Registry.GetValue(value.ToString, "DateLastConnected", Nothing)
            Dim dt As DateTime = ObterDataDoUltimoAcesso(data)

            lDatas.Add(New KeyValuePair(Of String, Date)(SubK, dt))
        Next

        lDatas = lDatas.OrderByDescending(Function(x) x.Value).ToList
        Dim t = lDatas.First
        Dim chave = My.Computer.Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles\" + t.Key)
        Dim nomeRede As String = My.Computer.Registry.GetValue(chave.ToString, "ProfileName", Nothing)
        Dim tipoRede As String = My.Computer.Registry.GetValue(chave.ToString, "Category", Nothing)

        NomeDaRede = nomeRede
        Select Case tipoRede
            Case 0
                Me.PerfilDaRede = "Publica"
            Case 1
                Me.PerfilDaRede = "Privada"
            Case 2
                Me.PerfilDaRede = "Dominio"
        End Select

        Me.PreencherGriddgvDadosComputador(NomeConfiguracao, NomeDaRede, "Ok")
        Me.PreencherGriddgvDadosComputador(NomeConfiguracaoDois, Me.PerfilDaRede, "Ok")

    Catch ex As Exception
        MsgBox("Teste", vbInformation)
    End Try

End Sub
Author: Pedro Gaspar, 2018-03-14

1 answers

In the question you said:
if this option is ticked my code does not work on 64-bit system, but if I disable my application does not work on 32-bit machine.

Actually, if the field value target CPU is AnyCPU , and the option prefers 32-bit if is not checked, your program will adapt to the system you are running on: if the system is 32-bit, your program will run as 32-bit, if the system is 64-bit, your program will run as 64-bit. But if the option Prefer 32-bit is checked, your program will run as 32-bit, even if the system is 64-bit.

The problem is that on 64-bit Windows systems, if your program is 32-bit, it will run automatically on a subsystem called WOW64 (Windows 32-bit on Windows 64-bit), and in the case of Windows registry there is something called Registry Redirector , which intercepts calls to the registry and redirects them to the correct location, based on the application architecture (32 or 64 bits).

More on the subject in the links below:

Running 32-bit Applications
https://msdn.microsoft.com/en-us/library/windows/desktop/aa384249.aspx

Registry Redirector
https://msdn.microsoft.com/en-us/library/windows/desktop/aa384232.aspx

Today when searching to answer your question, I found that since the .NET Framework 4.0, there is an option in the Windows Registry manipulation classes that allows you to access a 64-bit key through a 32-bit application, i.e. an option that temporarily disables the registry redirector:

Method RegistryKey.OpenBaseKey (RegistryHive, RegistryView)
https://msdn.microsoft.com/pt-br/library/microsoft.win32.registrykey.openbasekey.aspx

Enumeration RegistryView
https://msdn.microsoft.com/pt-br/library/microsoft.win32.registryview.aspx

Members
RegistryView.Default -> the default display.
RegistryView.Registry32 -> the 32-bit display.
RegistryView.Registry64 -> the 64-bit display.

Comments
in the 64-bit version of Windows, parts of the registry are stored separately for 32-bit and 64-bit applications. There is a 32-bit view for 32-bit applications and a 64-bit view for 64-bit applications.

you can specify a log view by using the OpenBaseKey and OpenRemoteBaseKey(RegistryHive, String, RegistryView) methods and the FromHandle property on a RegistryKey object.

if you request a 64-bit view on a 32-bit operating system, the keys are returned in 32-bit view.

By changing your code to use this method, and accessing 64-bit keys even through a 32-bit application:

Imports Microsoft.Win32

' [...]

   Public Sub ObterTipoDaRede(NomeConfiguracao As String, NomeConfiguracaoDois As String)

      Const NomeChaveProfiles = 
         "SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles"

      Dim chaveBase As RegistryKey
      Dim chaveProfiles As RegistryKey
      Dim chaveProfile As RegistryKey
      Dim listaDatas As New List(Of KeyValuePair(Of String, DateTime))

      ' Se você solicitar um modo de exibição de 64 bits em um sistema operacional
      ' de 32 bits, as chaves serão retornadas no modo de exibição de 32 bits.
      chaveBase = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
                                          RegistryView.Registry64)
      chaveProfiles = chaveBase.OpenSubKey(NomeChaveProfiles)

      For Each nomeChaveProfile In chaveProfiles.GetSubKeyNames
         chaveProfile = chaveBase.OpenSubKey(NomeChaveProfiles & "\" + nomeChaveProfile)
         Dim dataFormatoBinario = chaveProfile.GetValue("DateLastConnected", Nothing)
         Dim dt As DateTime = ObterDataDoUltimoAcesso(dataFormatoBinario)

         listaDatas.Add(New KeyValuePair(Of String, Date)(nomeChaveProfile, dt))
      Next

      listaDatas = listaDatas.OrderByDescending(Function(x) x.Value).ToList()
      Dim primeiroItem = listaDatas.First()
      chaveProfile = chaveBase.OpenSubKey(NomeChaveProfiles & "\" + primeiroItem.Key)
      Dim nomeRede As String = chaveProfile.GetValue("ProfileName", Nothing)
      Dim tipoRede As String = chaveProfile.GetValue("Category", Nothing)

      Select Case tipoRede
         Case 0 : Me.PerfilDaRede = "Publica"
         Case 1 : Me.PerfilDaRede = "Privada"
         Case 2 : Me.PerfilDaRede = "Dominio"
      End Select

   End Sub
 2
Author: Pedro Gaspar, 2018-03-15 03:27:45