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

Asked

Viewed 160 times

1

I need to get information related to the network to list in an application I’m doing, but I have a problem accessing the Registry Windows because of project preference.

Path: Right-click the class, click properties, and then compiler.

Note that below the Target CPU field, has a Checkbox (Prefer 32-bit)

If this option is ticada my code does not work on 64 bit system, however if I disable my application does not work on 32 bit machine. If I comment on all procedures that seek values in regedit, the application works on both.

I wonder if I can access the registry key in both 64bit and 32 bit.

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
  • Se essa opção estiver ticada meu código não funciona, porém se eu desabilitar minha aplicação não funciona na máquina 32 bits. If I understand correctly your code does not work regardless of whether the option is enabled or not.

  • If it’s not keyed, it works on 64-bit systems, but on 32-bit systems it doesn’t work.Any procedure I create to access regedit to get a value I can’t run on both systems.

1 answer

2

On the question you said:
If this option is ticada my code does not work on 64 bit system, however if I disable my application does not work on 32 bit machine.

In fact, if the value of the field Target CPU for Anycpu, and the option Prefer 32-bit nay is 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 Registry Windows there is something called Registry Redirector, who intercepts calls to 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 discovered that since . NET Framework 4.0, there is an option in the handling classes of Registry Windows that allows access to a 64-bit key through a 32-bit application, that is, 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 standard display.
Registryview.Registry32 -> The 32 bit display.
Registryview.Registry64 -> The 64 bit display.

Commentary
In the 64-bit version of Windows, portions of the registry are stored separately for 32-bit and 64-bit applications. There is a 32-bit display mode for 32-bit applications and a 64-bit display mode for 64-bit applications.

You can specify a record view mode when using methods OpenBaseKey and OpenRemoteBaseKey(RegistryHive, String, RegistryView) and the property FromHandle in an object RegistryKey.

If you request a 64-bit display mode on a 32-bit operating system, the keys will be returned in 32-bit display mode.

Changing your code to use this method, and accessing the 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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.