2009-09-24 11 views
6

Estoy encontrando un comportamiento extraño con un módulo .NET accediendo al Windows Registry usando la clase RegistryKey.¿Accediendo al registro de Windows usando .NET?

Por ejemplo, he escrito un módulo .NET, testcom.dll, que accede al registro. Este archivo testcom.dll es utilizado tanto por una aplicación nativa de 32 bits como por una de 64 bits. Mi requisito es obtener el valor de una clave de registro (la ruta es HKEY_LOCAL_MACHINE\SOFTWARE\Test\MyParameters y el nombre de la clave es Age). Esta clave "Age" estará en el registro de 32 bits en máquinas de 32 bits y el registro de 64 bits (no WOW64) en máquinas de 64 bits.

En una máquina de 64 bits, cuando una aplicación de 32 bits utiliza testcom.dll, la clave "Edad" se busca en el registro WOW64. Cuando una aplicación de 64 bits usa testcom.dll, se busca la clave "Edad" en el registro de 64 bits.

Mi requisito es leer la clave en el registro de 64 bits en máquinas de 64 bits, sea cual sea la aplicación utiliza el archivo testcom.dll. ¿Cómo puedo hacer esto?

+0

Eso es extraño. Cuando una vez escribí una aplicación que buscaba claves y valores en el registro, tuve que modificar manualmente la ruta para las claves de aplicación de 32 bits cuando se ejecutaba en un sistema operativo de 64 bits. ¿Podría publicar algún código, tal vez? Para ver si su método de carga de las claves difiere de la mía? –

+0

También la aplicación era una aplicación de 32 bits. No buscó WOW64 de manera predeterminada. –

Respuesta

4

he tenido un problema similar, y la mejor respuesta que he encontrado es a caer de nuevo a las funciones de Win32 de registro (tal como RegOpenKeyEx) y pase el apropiado Registry Key Security and Access Rights, OR'ing específicamente el parámetro samDesired con el KEY_WOW64_64KEY .

Fue horrible, y espero que escuches una mejor respuesta aquí.

+0

Gracias por su respuesta. También espero lo mejor :) –

+0

Gracias finalmente una respuesta que parece funcionar. – rogerdpack

2

La respuesta de Blair con respecto a volver a la API de Win32 y llamar a la función RegOpenKeyEx es la mejor manera de lograr esto.

Windows mismo mapeará ubicaciones de registro específicas en vistas lógicas utilizando Registry Redirector y Registry Reflection.

Puede leer más sobre este proceso en el siguiente artículo de MSDN:
32-bit and 64-bit Application Data in the Registry

A pesar de la API de Win32 es la mejor manera de lograr esto, esto es la posibilidad de "codificación dura" la ubicación de la registro que está tratando de recuperar, aunque esto está plagado de posibles problemas (Microsoft mismo no es compatible con este método). Puede leer más sobre esto en este desbordamiento de pila Pregunta:
How to open a WOW64 registry key from a 64-bit .NET application

En última instancia, la API de Win32 parece acerca de la mejor solución (si no el más elegante) en el momento.
Heath Stewart de Microsoft dicta la siguiente respuesta en this MSDN Social pregunta:

Desafortunadamente no hay una manera de pasar esas banderas a los API de registro administrados bajo la Microsoft.Win32 espacio de nombres. Debería tener que P/Invocar la API nativa tal como RegCreateKeyEx que mencionó.

Considere, sin embargo, si necesita almacenar datos en una vista de 32 o 64 bits de el registro.El tema Registro redirector en MSDN tiene las llaves que se redirigen , que es probable que estés familiarizado con , y el tema del registro reflexión tiene las claves en las que valores se copian entre 32 y claves de 64 bits.

Si, efectivamente, que necesita puntos de vista distintos, que También puede considerar que permite registro reflexión para sus llaves si lo desea tanto a sus 32 y 64 bits aplicaciones compartir al menos algunos datos del registro. Consulte la documentación para RegEnableReflectionKey para obtener más información sobre .

2

En el siguiente código, GetAge() devolverá el valor de su clave, o nulo si la clave no existe.

[DllImport("Advapi32.dll")] 
static extern uint RegOpenKeyEx(UIntPtr hKey, string lpSubKey, uint ulOptions, int samDesired, out int phkResult); 
[DllImport("Advapi32.dll")] 
static extern uint RegCloseKey(int hKey); 
[DllImport("advapi32.dll", EntryPoint = "RegQueryValueEx")] 
public static extern int RegQueryValueEx(int hKey, string lpValueName, int lpReserved, ref uint lpType, System.Text.StringBuilder lpData, ref uint lpcbData); 

public const int KEY_QUERY_VALUE = 0x0001; 
public const int KEY_WOW64_64KEY = 0x0100; 

static public string GetAge() 
{ 
    string EPG_REGKEY = @"SOFTWARE\Test\MyParameters"; 
    UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002; 
    int hkey = 0; 

    try 
    { 
     uint lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, EPG_REGKEY, 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, out hkey); 
     if (0 != lResult) return null; 
     uint lpType = 0; 
     uint lpcbData = 1024; 
     StringBuilder AgeBuffer = new StringBuilder(1024); 
     RegQueryValueEx(hkey, "Age", 0, ref lpType, AgeBuffer, ref lpcbData); 
     string Age = AgeBuffer.ToString(); 
     return Age; 
    } 
    finally 
    { 
     if (0 != hkey) RegCloseKey(hkey); 
    } 
} 
9

Si puede cambiar la versión .NET de destino a v4, puede utilizar la nueva función OpenBaseKey, p.

RegistryKey registryKey; 
if (Environment.Is64BitOperatingSystem == true) 
{ 
    registryKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64); 
} 
else 
{ 
    registryKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry32); 
} 
Cuestiones relacionadas