Todavía hay soporte nativo para el acceso al registro de 64 bits bajo Windows utilizando 4.x de .NET Framework . El siguiente código se prueba con Windows 7, 64 bit y también con Windows 10, 64 bit .
En lugar de usar "Wow6432Node"
, que emula un nodo al mapear un árbol de registro en otro para que aparezca allí virtualmente, puede hacer lo siguiente:
Decida si necesita acceder al registro de 64 bits o de 32 bits y utilícelo como se describe a continuación. También puede usar el código que mencioné más adelante (sección de información adicional), que crea una consulta de unión para obtener claves de registro de ambos nodos en una consulta, por lo que aún puede consultarlos utilizando su ruta real.
Registro de 64 bits
Para acceder al registro de 64 bits , puede utilizar RegistryView.Registry64
lo siguiente:
string value64 = string.Empty;
RegistryKey localKey =
RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine,
RegistryView.Registry64);
localKey = localKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
if (localKey != null)
{
value64 = localKey.GetValue("RegisteredOrganization").ToString();
localKey.Close();
}
Console.WriteLine(String.Format("RegisteredOrganization [value64]: {0}",value64));
Registro de 32 bits
Si desea acceder al registro de 32 bits , utilice RegistryView.Registry32
lo siguiente:
string value32 = string.Empty;
RegistryKey localKey32 =
RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine,
RegistryView.Registry32);
localKey32 = localKey32.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
if (localKey32 != null)
{
value32 = localKey32.GetValue("RegisteredOrganization").ToString();
localKey32.Close();
}
Console.WriteLine(String.Format("RegisteredOrganization [value32]: {0}",value32));
No se confunda, ambas versiones están usando Microsoft.Win32.RegistryHive.LocalMachine
como primer parámetro, usted hace la distinción entre usar 64 bits o 32 bits por el segundo parámetro ( RegistryView.Registry64
versus RegistryView.Registry32
).
Nota que
En Windows de 64 bits, HKEY_LOCAL_MACHINE\Software\Wow6432Node
contiene valores utilizados por aplicaciones de 32 bits que se ejecutan en el sistema de 64 bits. Solo las verdaderas aplicaciones de 64 bits almacenan sus valores HKEY_LOCAL_MACHINE\Software
directamente. El subárbol Wow6432Node
es completamente transparente para aplicaciones de 32 bits, las aplicaciones de 32 bits todavía ven HKEY_LOCAL_MACHINE\Software
como lo esperan (es una especie de redirección). En versiones anteriores de Windows, así como en Windows 7 de 32 bits (y Vista de 32 bits), el subárbol Wow6432Node
obviamente no existe.
Debido a un error en Windows 7 (64 bits), la versión del código fuente de 32 bits siempre devuelve "Microsoft" independientemente de la organización que haya registrado, mientras que la versión del código fuente de 64 bits devuelve la organización correcta.
Volviendo al ejemplo que ha proporcionado, hágalo de la siguiente manera para acceder a la rama de 64 bits:
RegistryKey localKey =
RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine,
RegistryView.Registry64);
RegistryKey sqlServerKey = localKey.OpenSubKey(
@"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL");
string sqlExpressKeyName = (string) sqlServerKey.GetValue("SQLEXPRESS");
Información adicional - para uso práctico:
Me gustaría agregar un enfoque interesante que Johny Skovdal ha sugerido en los comentarios, que he recogido para desarrollar algunas funciones útiles utilizando su enfoque: En algunas situaciones, desea recuperar todas las claves independientemente de si es de 32 bits o 64 bits. Los nombres de las instancias de SQL son un ejemplo. Puede usar una consulta de unión en ese caso de la siguiente manera (C # 6 o superior):
// using Microsoft.Win32;
public static IEnumerable<string> GetRegValueNames(RegistryView view, string regPath,
RegistryHive hive = RegistryHive.LocalMachine)
{
return RegistryKey.OpenBaseKey(hive, view)
?.OpenSubKey(regPath)?.GetValueNames();
}
public static IEnumerable<string> GetAllRegValueNames(string RegPath,
RegistryHive hive = RegistryHive.LocalMachine)
{
var reg64 = GetRegValueNames(RegistryView.Registry64, RegPath, hive);
var reg32 = GetRegValueNames(RegistryView.Registry32, RegPath, hive);
var result = (reg64 != null && reg32 != null) ? reg64.Union(reg32) : (reg64 ?? reg32);
return (result ?? new List<string>().AsEnumerable()).OrderBy(x => x);
}
public static object GetRegValue(RegistryView view, string regPath, string ValueName="",
RegistryHive hive = RegistryHive.LocalMachine)
{
return RegistryKey.OpenBaseKey(hive, view)
?.OpenSubKey(regPath)?.GetValue(ValueName);
}
public static object GetRegValue(string RegPath, string ValueName="",
RegistryHive hive = RegistryHive.LocalMachine)
{
return GetRegValue(RegistryView.Registry64, RegPath, ValueName, hive)
?? GetRegValue(RegistryView.Registry32, RegPath, ValueName, hive);
}
public static IEnumerable<string> GetRegKeyNames(RegistryView view, string regPath,
RegistryHive hive = RegistryHive.LocalMachine)
{
return RegistryKey.OpenBaseKey(hive, view)
?.OpenSubKey(regPath)?.GetSubKeyNames();
}
public static IEnumerable<string> GetAllRegKeyNames(string RegPath,
RegistryHive hive = RegistryHive.LocalMachine)
{
var reg64 = GetRegKeyNames(RegistryView.Registry64, RegPath, hive);
var reg32 = GetRegKeyNames(RegistryView.Registry32, RegPath, hive);
var result = (reg64 != null && reg32 != null) ? reg64.Union(reg32) : (reg64 ?? reg32);
return (result ?? new List<string>().AsEnumerable()).OrderBy(x => x);
}
Ahora puede simplemente usar las funciones anteriores de la siguiente manera:
Ejemplo 1: obtener nombres de instancias SQL
var sqlRegPath=@"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL";
foreach (var valueName in GetAllRegValueNames(sqlRegPath))
{
var value=GetRegValue(sqlRegPath, valueName);
Console.WriteLine($"{valueName}={value}");
}
le dará una lista de los nombres y valores de los valores en sqlRegPath.
Nota: Puede acceder al valor predeterminado de una clave (mostrado por la herramienta de línea de comandos REGEDT32.EXE
como (Default)
) si omite el ValueName
parámetro en las funciones correspondientes anteriores.
Para obtener una lista de subclaves dentro de una clave de registro, use la función GetRegKeyNames
o GetAllRegKeyNames
. Puede utilizar esta lista para recorrer más claves en el registro.
Ejemplo 2: obtener información de desinstalación del software instalado
var currentVersionRegPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion";
var uninstallRegPath = $@"{currentVersionRegPath}\Uninstall";
var regKeys = Registry.GetAllRegKeyNames(RegPath: uninstallRegPath);
obtendrá todas las claves de desinstalación de 32 y 64 bits.
Observe el manejo de nulos requerido en las funciones porque el servidor SQL se puede instalar como 32 bits o como 64 bits (ejemplo 1 anterior). Las funciones están sobrecargadas, por lo que aún puede pasar el parámetro de 32 bits o 64 bits si es necesario; sin embargo, si lo omite, intentará leer 64 bits, si eso falla (valor nulo), lee los valores de 32 bits.
Aquí hay una especialidad: debido a GetAllRegValueNames
que generalmente se usa en un contexto de bucle (consulte el Ejemplo 1 anterior), devuelve un enumerable vacío en lugar de null
simplificar los foreach
bucles: si no se manejara de esa manera, el bucle debería tener el prefijo una if
comprobación de sentencias para la null
que sería engorroso tener que hacer eso, de modo que se trata una vez en la función.
¿Por qué preocuparse por null? Porque si no le importa, tendrá muchos más dolores de cabeza al descubrir por qué se incluyó esa excepción de referencia nula en su código: pasaría mucho tiempo averiguando dónde y por qué sucedió. Y si sucedió en producción, estará muy ocupado estudiando archivos de registro o registros de eventos (espero que haya implementado el registro) ... mejor evite los problemas de nulos cuando pueda de manera defensiva. Los operadores ?.
, ?[
... ]
y ??
pueden ayudarlo mucho (consulte el código proporcionado arriba). Hay un buen artículo relacionado sobre los nuevos tipos de referencia que aceptan valores NULL en C # , que recomiendo leer y también este sobre el operador de Elvis.
Sugerencia: puede usar la edición gratuita de Linqpad para probar todos los ejemplos en Windows. No requiere instalación. No olvide presionar F4e ingresar Microsoft.Win32
en la pestaña Importar espacio de nombres. En Visual Studio, necesita using Microsoft.Win32;
en la parte superior de su código.
Sugerencia: para familiarizarse con los nuevos operadores de manejo de nulos , pruebe (y depure) el siguiente código en LinqPad:
Ejemplo 3: demostración de operadores de manejo de nulos
static string[] test { get { return null;} } // property used to return null
static void Main()
{
test.Dump(); // output: null
// "elvis" operator:
test?.Dump(); // output:
// "elvis" operator for arrays
test?[0].Dump(); // output:
(test?[0]).Dump(); // output: null
// combined with null coalescing operator (brackets required):
(test?[0]??"<null>").Dump(); // output: "<null>"
}
Pruébalo con .Net violín
Si está interesado, aquí hay algunos ejemplos que reuní y que muestran qué más puede hacer con la herramienta.