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
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.aspxRegistry 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.aspxEnumeration RegistryView
https://msdn.microsoft.com/pt-br/library/microsoft.win32.registryview.aspxMembers
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
andOpenRemoteBaseKey(RegistryHive, String, RegistryView)
methods and theFromHandle
property on aRegistryKey
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