C'è ancora il supporto nativo per l'accesso al registro in Windows a 64 bit utilizzando 4.x .NET Framework . Il codice seguente viene testato con Windows 7, 64 bit e anche con Windows 10, 64 bit .
Invece di usare "Wow6432Node"
, che emula un nodo mappando un albero del registro in un altro facendolo apparire virtualmente, puoi fare quanto segue:
Decidi se devi accedere al registro a 64 bit oa 32 bit e usalo come descritto di seguito. Puoi anche utilizzare il codice che ho menzionato più avanti (sezione Informazioni aggiuntive), che crea una query di unione per ottenere le chiavi di registro da entrambi i nodi in una query, quindi puoi comunque interrogarli usando il loro percorso reale.
Registro a 64 bit
Per accedere al registro a 64 bit , è possibile utilizzare RegistryView.Registry64
quanto segue:
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 a 32 bit
Se desideri accedere al registro a 32 bit , utilizza RegistryView.Registry32
quanto segue:
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));
Non essere confuso, entrambe le versioni utilizzano Microsoft.Win32.RegistryHive.LocalMachine
come primo parametro, fai la distinzione se utilizzare 64 bit o 32 bit dal 2 ° parametro ( RegistryView.Registry64
contro RegistryView.Registry32
).
Nota quello
Su Windows a 64 bit, HKEY_LOCAL_MACHINE\Software\Wow6432Node
contiene i valori utilizzati dalle applicazioni a 32 bit in esecuzione sul sistema a 64 bit. Solo le vere applicazioni a 64 bit memorizzano HKEY_LOCAL_MACHINE\Software
direttamente i propri valori . La sottostruttura Wow6432Node
è completamente trasparente per le applicazioni a 32 bit, le applicazioni a 32 bit vedono ancora HKEY_LOCAL_MACHINE\Software
come si aspettano (è una sorta di reindirizzamento). Nelle versioni precedenti di Windows e in Windows 7 a 32 bit (e Vista a 32 bit) la sottostruttura Wow6432Node
ovviamente non esiste.
A causa di un bug in Windows 7 (64 bit), la versione del codice sorgente a 32 bit restituisce sempre "Microsoft" indipendentemente dall'organizzazione registrata, mentre la versione del codice sorgente a 64 bit restituisce l'organizzazione corretta.
Tornando all'esempio che hai fornito, fallo nel modo seguente per accedere al ramo a 64 bit:
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");
Informazioni aggiuntive - per uso pratico:
Vorrei aggiungere un approccio interessante che Johny Skovdal ha suggerito nei commenti, che ho raccolto per sviluppare alcune funzioni utili utilizzando il suo approccio: in alcune situazioni si desidera recuperare tutte le chiavi indipendentemente dal fatto che sia a 32 bit o 64 bit. I nomi delle istanze SQL sono un esempio di questo tipo. In tal caso è possibile utilizzare una query di unione come segue (C # 6 o versione successiva):
// 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);
}
Ora puoi semplicemente usare le funzioni sopra come segue:
Esempio 1: ottenere i nomi delle istanze 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}");
}
ti fornirà un elenco dei nomi dei valori e dei valori in sqlRegPath.
Nota: è possibile accedere al valore predefinito di una chiave (visualizzato dallo strumento della riga di comando REGEDT32.EXE
come (Default)
) se si omette il ValueName
parametro nelle funzioni corrispondenti sopra.
Per ottenere un elenco di sottochiavi all'interno di una chiave di registro, utilizzare la funzione GetRegKeyNames
o GetAllRegKeyNames
. È possibile utilizzare questo elenco per attraversare ulteriori chiavi nel registro.
Esempio 2: ottenere informazioni sulla disinstallazione del software installato
var currentVersionRegPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion";
var uninstallRegPath = $@"{currentVersionRegPath}\Uninstall";
var regKeys = Registry.GetAllRegKeyNames(RegPath: uninstallRegPath);
otterrà tutte le chiavi di disinstallazione a 32 bit e 64 bit.
Notare la gestione null richiesta nelle funzioni perché SQL Server può essere installato a 32 bit o 64 bit (esempio 1 sopra). Le funzioni sono sovraccariche in modo da poter ancora passare il parametro a 32 bit o 64 bit se necessario, tuttavia, se lo si omette, proverà a leggere 64 bit, se fallisce (valore nullo), legge i valori a 32 bit.
C'è una specialità qui: poiché GetAllRegValueNames
viene solitamente utilizzato in un contesto di ciclo (vedere l'Esempio 1 sopra), restituisce un enumerabile vuoto piuttosto che null
semplificare i foreach
cicli: se non fosse gestito in questo modo, il ciclo dovrebbe essere preceduto da un if
controllo economico null
che sarebbe ingombrante dover fare - così che è oggetto di una volta in funzione.
Perché preoccuparsi di null? Perché se non ti interessa, avrai molti più mal di testa a scoprire perché quell'eccezione di riferimento nullo è stata lanciata nel tuo codice: passeresti molto tempo a scoprire dove e perché è successo. E se è accaduto in produzione sarai molto impegnato a studiare i file di log o i log degli eventi (spero che tu abbia implementato il log) ... meglio evitare problemi nulli dove puoi in modo difensivo. Gli operatori ?.
, ?[
... ]
e ??
possono aiutarti molto (vedi il codice fornito sopra). C'è un bell'articolo correlato che discute i nuovi tipi di riferimento nullable in C # , che consiglio di leggere e anche questo sull'operatore Elvis.
Suggerimento: puoi usare l'edizione gratuita di Linqpad per testare tutti gli esempi sotto Windows. Non richiede installazione. Non dimenticare di premere F4e accedere Microsoft.Win32
alla scheda di importazione dello spazio dei nomi. In Visual Studio, è necessario using Microsoft.Win32;
nella parte superiore del codice.
Suggerimento: per familiarizzare con i nuovi operatori di gestione dei valori nulli , provare (ed eseguire il debug) del codice seguente in LinqPad:
Esempio 3: dimostrazione di operatori di gestione null
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>"
}
Provalo con .Net fiddle
Se sei interessato, ecco alcuni esempi che ho messo insieme che mostrano cos'altro puoi fare con lo strumento.