2009-09-24 7 views
6

Sto riscontrando uno strano comportamento con un modulo .NET che accede a Windows Registry utilizzando la classe RegistryKey.Accesso al registro di Windows tramite .NET?

Ad esempio, ho scritto un modulo .NET, testcom.dll, che accede al registro. Questo file testcom.dll viene utilizzato sia da un'applicazione nativa a 32 bit che da un'applicazione a 64 bit. Il mio requisito è quello di ottenere il valore di un regkey (il percorso è HKEY_LOCAL_MACHINE\SOFTWARE\Test\MyParameters e il nome della chiave è Age). Questa chiave "Age" sarà nel registro a 32 bit su macchine a 32 bit e registro a 64 bit (non WOW64) su macchine a 64 bit.

Su una macchina a 64 bit, quando un'applicazione a 32 bit utilizza testcom.dll, la chiave "Età" viene cercata nel registro WOW64. Quando un'applicazione a 64 bit utilizza testcom.dll, la chiave "Età" viene cercata nel registro a 64 bit.

Il mio requisito è quello di leggere la chiave nel registro a 64 bit su macchine a 64 bit qualunque sia l'applicazione utilizza il file testcom.dll. Come posso fare questo?

+0

Questo è dispari. Quando una volta scrissi un'app che cercava chiavi e valori nel registro, dovevo modificare manualmente il percorso per le chiavi delle applicazioni a 32 bit quando si eseguiva su un sistema operativo a 64 bit. Potresti postare qualche codice forse? Per vedere se il tuo metodo di caricamento delle chiavi è diverso dal mio? –

+0

Anche l'applicazione era un'app a 32 bit. Di default non ha cercato WOW64. –

risposta

4

ho avuto un problema simile, e la risposta migliore che ho trovato è quello di ricadere le funzioni Win32 del Registro di sistema (come ad esempio RegOpenKeyEx) e passare il appropriata Registry Key Security and Access Rights, specificamente OR nel parametro parametro samDesired con l'KEY_WOW64_64KEY .

E 'stato orribile, e spero che tu senta una risposta migliore qui.

+0

Grazie per la tua risposta. Spero anche per il meglio :) –

+0

Grazie infine una risposta che sembra funzionare. – rogerdpack

2

La risposta di Blair relativa al ripristino dell'API Win32 e al richiamo della funzione RegOpenKeyEx all'interno rappresenta il modo migliore per ottenere ciò.

Windows stesso associerà posizioni di registro specifiche in viste logiche utilizzando uno Registry Redirector e Registry Reflection.

Si può leggere di più su questo processo nel seguente articolo di MSDN:
32-bit and 64-bit Application Data in the Registry

Nonostante l'API Win32 è il modo migliore per raggiungere questo obiettivo, questa è la possibilità di "codificare" la posizione del registro che si sta cercando di recuperare, anche se questo è irto di possibili problemi (gli stessi Microsoft non supportano questo metodo). Si può leggere di più su questo in questo Stack Overflow Domanda:
How to open a WOW64 registry key from a 64-bit .NET application

In ultima analisi, l'API Win32 sembra sul punto la soluzione migliore (se non il più elegante) in questo momento.
Heath Stewart da Microsoft ha pronunciato la seguente risposta in this MSDN Social domanda:

Purtroppo non v'è un modo per passare quelle bandiere alle API del Registro di sistema gestiti nell'ambito del Microsoft.Win32 namespace . Dovresti avere P/Richiamare l'API nativa come come RegCreateKeyEx che hai menzionato.

Considerare, tuttavia, se è necessario memorizzare i dati di in una vista a 32 o 64 bit del registro .Il tema del Registro Redirector in MSDN ha le chiavi che vengono reindirizzati , che probabilmente stai familiarità con, e l'argomento del Registro Riflessione ha le chiavi in ​​cui vengono copiati valori compresi tra 32 e chiavi a 64 bit.

Se davvero avete bisogno viste separate, si potrebbe anche considerare consentendo registro riflessione per le chiavi, se si desidera entrambe le 32 e 64 bit delle applicazioni condividere almeno alcuni dei dati del Registro di sistema. Vedere la documentazione per RegEnableReflectionKey per ulteriori dettagli .

2

Nel seguente codice, GetAge() restituirà il valore della chiave o null se la chiave non esiste.

[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

Se è possibile modificare il target versione di .NET per v4, quindi è possibile utilizzare la nuova funzione OpenBaseKey esempio

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); 
}