Il y a encore un support natif pour l' accès au Registre sous Windows 64 bits en utilisant 4.x .NET Framework . Le code suivant est testé avec Windows 7, 64 bits et également avec Windows 10, 64 bits .
Au lieu d'utiliser "Wow6432Node"
, qui émule un nœud en mappant une arborescence de registre dans une autre en la faisant apparaître virtuellement, vous pouvez faire ce qui suit:
Décidez si vous devez accéder au registre 64 bits ou 32 bits et utilisez-le comme décrit ci-dessous. Vous pouvez également utiliser le code que j'ai mentionné plus tard (section Informations supplémentaires), qui crée une requête d'union pour obtenir les clés de registre des deux nœuds en une seule requête - afin que vous puissiez toujours les interroger en utilisant leur chemin réel.
Registre 64 bits
Pour accéder au registre 64 bits , vous pouvez utiliser RegistryView.Registry64
comme suit:
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));
Registre 32 bits
Si vous souhaitez accéder au registre 32 bits , procédez RegistryView.Registry32
comme suit:
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));
Ne soyez pas confus, les deux versions utilisent Microsoft.Win32.RegistryHive.LocalMachine
comme premier paramètre, vous faites la distinction entre utiliser 64 bits ou 32 bits par le 2ème paramètre ( RegistryView.Registry64
versus RegistryView.Registry32
).
Notez que
Sur un Windows 64 bits, HKEY_LOCAL_MACHINE\Software\Wow6432Node
contient les valeurs utilisées par les applications 32 bits exécutées sur le système 64 bits. Seules les vraies applications 64 bits stockent leurs valeurs HKEY_LOCAL_MACHINE\Software
directement. Le sous Wow6432Node
- arbre est entièrement transparent pour les applications 32 bits, les applications 32 bits voient toujours HKEY_LOCAL_MACHINE\Software
comme elles l'attendent (c'est une sorte de redirection). Dans les anciennes versions de Windows ainsi que dans Windows 7 32 bits (et Vista 32 bits), le sous-arbre Wow6432Node
n'existe évidemment pas .
En raison d'un bogue dans Windows 7 (64 bits), la version de code source 32 bits renvoie toujours "Microsoft" quelle que soit l'organisation que vous avez enregistrée tandis que la version de code source 64 bits renvoie la bonne organisation.
Pour revenir à l'exemple que vous avez fourni, procédez de la manière suivante pour accéder à la branche 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");
Informations complémentaires - pour une utilisation pratique:
J'aimerais ajouter une approche intéressante que Johny Skovdal a suggérée dans les commentaires, que j'ai choisie pour développer des fonctions utiles en utilisant son approche: dans certaines situations, vous voulez récupérer toutes les clés, qu'elles soient 32 bits ou 64 bits. Les noms d'instances SQL en sont un exemple. Vous pouvez utiliser une requête Union dans ce cas comme suit (C # 6 ou supérieur):
// 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);
}
Maintenant, vous pouvez simplement utiliser les fonctions ci-dessus comme suit:
Exemple 1: obtenir les noms d'instances 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}");
}
vous donnera une liste des noms de valeur et des valeurs dans sqlRegPath.
Remarque: Vous pouvez accéder à la valeur par défaut d'une touche (affichée par l'outil de ligne de commande REGEDT32.EXE
sous la forme (Default)
) si vous omettez le ValueName
paramètre dans les fonctions correspondantes ci-dessus.
Pour obtenir une liste des sous- clés dans une clé de registre, utilisez la fonction GetRegKeyNames
ouGetAllRegKeyNames
. Vous pouvez utiliser cette liste pour parcourir d'autres clés dans le registre.
Exemple 2: obtenir des informations de désinstallation du logiciel installé
var currentVersionRegPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion";
var uninstallRegPath = $@"{currentVersionRegPath}\Uninstall";
var regKeys = Registry.GetAllRegKeyNames(RegPath: uninstallRegPath);
obtiendra toutes les clés de désinstallation 32 bits et 64 bits.
Notez le traitement nul requis dans les fonctions car le serveur SQL peut être installé en 32 bits ou en 64 bits (exemple 1 ci-dessus). Les fonctions sont surchargées afin que vous puissiez toujours passer le paramètre 32 bits ou 64 bits si nécessaire - cependant, si vous l'omettez, il essaiera de lire 64 bits, si cela échoue (valeur nulle), il lit les valeurs 32 bits.
Il y a une spécialité ici: comme il GetAllRegValueNames
est généralement utilisé dans un contexte de boucle (voir l'exemple 1 ci-dessus), il retourne un énumérable vide plutôt que null
de simplifier les foreach
boucles: s'il ne serait pas géré de cette façon, la boucle devrait être préfixée par une if
déclaration vérifiantnull
lequel il serait fastidieux de devoir faire cela - donc cela est traité une fois dans la fonction.
Pourquoi se soucier de null? Parce que si vous ne vous en souciez pas, vous aurez beaucoup plus de maux de tête pour savoir pourquoi cette exception de référence nulle a été lancée dans votre code - vous passeriez beaucoup de temps à découvrir où et pourquoi cela s'est produit. Et si cela s'est produit en production, vous serez très occupé à étudier les fichiers journaux ou les journaux d'événements (j'espère que vous avez implémenté la journalisation) ... mieux vaut éviter les problèmes de nullité lorsque vous le pouvez de manière défensive. Les opérateurs ?.
, ?[
... ]
et ??
peuvent beaucoup vous aider (voir le code fourni ci-dessus). Il y a un bel article connexe traitant des nouveaux types de référence nullable en C # , que je recommande de lire et aussi celui-ci sur l'opérateur Elvis.
Astuce: vous pouvez utiliser l'édition gratuite de Linqpad pour tester tous les exemples sous Windows. Il ne nécessite pas d'installation. N'oubliez pas d'appuyer sur F4et d'entrer Microsoft.Win32
dans l'onglet d'importation d'espace de noms. Dans Visual Studio, vous avez besoin using Microsoft.Win32;
en haut de votre code.
Conseil: pour vous familiariser avec les nouveaux opérateurs de gestion des valeurs nulles , essayez (et déboguez) le code suivant dans LinqPad:
Exemple 3: démonstration d'opérateurs de gestion nuls
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>"
}
Essayez-le avec .Net Fiddle
Si vous êtes intéressé, voici quelques exemples que j'ai rassemblés montrant ce que vous pouvez faire d'autre avec l'outil.