Jest jeszcze natywne wsparcie dla dostępu do rejestru w 64-bitowym systemie Windows przy użyciu .NET Framework 4.x . Poniższy kod jest testowany w systemie Windows 7 w wersji 64-bitowej, a także w systemie Windows 10 w wersji 64-bitowej .
Zamiast używać "Wow6432Node"
, które emuluje węzeł, mapując jedno drzewo rejestru na inne, dzięki czemu pojawia się tam wirtualnie, możesz wykonać następujące czynności:
Zdecyduj, czy potrzebujesz dostępu do rejestru 64-bitowego, czy 32-bitowego, i użyj go w sposób opisany poniżej. Możesz również użyć kodu, o którym wspomniałem później (sekcja Informacje dodatkowe), który tworzy zapytanie składające, aby uzyskać klucze rejestru z obu węzłów w jednym zapytaniu - dzięki czemu nadal możesz zapytać o nie, używając ich rzeczywistej ścieżki.
Rejestr 64-bitowy
Aby uzyskać dostęp do rejestru 64-bitowego , możesz użyć RegistryView.Registry64
następujących poleceń:
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));
Rejestr 32-bitowy
Jeśli chcesz uzyskać dostęp do rejestru 32-bitowego , użyj RegistryView.Registry32
następujących poleceń:
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));
Nie należy się mylić, obie wersje używają Microsoft.Win32.RegistryHive.LocalMachine
jako pierwszego parametru, rozróżniasz, czy użyć 64-bitowego czy 32-bitowego parametru przez drugi parametr (w RegistryView.Registry64
porównaniu RegistryView.Registry32
).
Zwróć na to uwagę
W 64-bitowym systemie Windows HKEY_LOCAL_MACHINE\Software\Wow6432Node
zawiera wartości używane przez aplikacje 32-bitowe działające w systemie 64-bitowym. Tylko prawdziwe 64-bitowe aplikacje przechowują swoje wartości HKEY_LOCAL_MACHINE\Software
bezpośrednio w. Poddrzewo Wow6432Node
jest całkowicie przezroczyste dla aplikacji 32-bitowych, aplikacje 32-bitowe nadal widzą to, HKEY_LOCAL_MACHINE\Software
czego oczekują (jest to rodzaj przekierowania). W starszych wersjach systemu Windows, a także w 32-bitowym systemie Windows 7 (i w systemie Vista w wersji 32-bitowej) poddrzewo Wow6432Node
oczywiście nie istnieje.
Z powodu błędu w systemie Windows 7 (64-bitowym), 32-bitowa wersja kodu źródłowego zawsze zwraca „Microsoft” niezależnie od zarejestrowanej organizacji, podczas gdy 64-bitowa wersja kodu źródłowego zwraca właściwą organizację.
Wracając do podanego przykładu, zrób to w następujący sposób, aby uzyskać dostęp do gałęzi 64-bitowej:
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");
Dodatkowe informacje - do praktycznego zastosowania:
Chciałbym dodać interesujące podejście, które zasugerował Johny Skovdal w komentarzach, które zebrałem, aby opracować kilka przydatnych funkcji za pomocą jego podejścia: W niektórych sytuacjach chcesz odzyskać wszystkie klawisze, niezależnie od tego, czy jest to 32-bitowy, czy 64-bitowy. Przykładem są nazwy instancji SQL. W takim przypadku można użyć zapytania składającego w następujący sposób (C # 6 lub nowszy):
// 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);
}
Teraz możesz po prostu użyć powyższych funkcji w następujący sposób:
Przykład 1: pobieranie nazw instancji 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}");
}
poda listę nazw wartości i wartości w sqlRegPath.
Uwaga: Możesz uzyskać dostęp do domyślnej wartości klucza (wyświetlanej przez narzędzie wiersza poleceń REGEDT32.EXE
jako (Default)
), jeśli pominiesz ValueName
parametr w odpowiednich funkcjach powyżej.
Aby uzyskać listę kluczy podrzędnych w kluczu rejestru, użyj funkcji GetRegKeyNames
lubGetAllRegKeyNames
. Możesz użyć tej listy do przechodzenia przez kolejne klucze w rejestrze.
Przykład 2: Uzyskaj informacje o odinstalowaniu zainstalowanego oprogramowania
var currentVersionRegPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion";
var uninstallRegPath = $@"{currentVersionRegPath}\Uninstall";
var regKeys = Registry.GetAllRegKeyNames(RegPath: uninstallRegPath);
otrzyma wszystkie 32-bitowe i 64-bitowe klucze deinstalacji.
Zwróć uwagę na obsługę zerową wymaganą w funkcjach, ponieważ serwer SQL można zainstalować jako 32-bitowy lub 64-bitowy (przykład 1 powyżej). Funkcje są przeciążone, więc w razie potrzeby nadal można przekazać parametr 32-bitowy lub 64-bitowy - jednak jeśli go pominiesz, spróbuje odczytać 64-bitowy, jeśli to się nie powiedzie (wartość zerowa), odczytuje wartości 32-bitowe.
Jest tu jedna specjalność: ponieważ GetAllRegValueNames
jest zwykle używana w kontekście pętli (patrz przykład 1 powyżej), zwraca raczej puste wyliczalne niż null
uproszczenie foreach
pętli: jeśli nie byłoby obsługiwane w ten sposób, pętla musiałaby być poprzedzona przedrostkiem if
oświadczenie sprawdzanienull
co byłoby uciążliwe konieczności zrobić - tak, aby zajmował się kiedyś w tej funkcji.
Po co zawracać sobie głowę nullem? Ponieważ jeśli cię to nie obchodzi, będziesz miał dużo więcej bólu głowy, gdy dowiesz się, dlaczego ten wyjątek zerowego odwołania został wrzucony do twojego kodu - spędzisz dużo czasu, aby dowiedzieć się, gdzie i dlaczego to się stało. A jeśli zdarzyło się to w środowisku produkcyjnym, będziesz bardzo zajęty studiowaniem plików dziennika lub dzienników zdarzeń (mam nadzieję, że masz zaimplementowane logowanie) ... lepiej unikaj błędów zerowych, gdzie możesz w obronny sposób. Operatorzy ?.
, ?[
... ]
i ??
może pomóc partii (patrz kod podany powyżej). Jest fajny powiązany artykuł omawiający nowe typy odwołań dopuszczających wartość null w C # , który polecam przeczytać, a także ten o operatorze Elvisa.
Wskazówka: możesz skorzystać z bezpłatnej edycji Linqpada, aby przetestować wszystkie przykłady w systemie Windows. Nie wymaga instalacji. Nie zapomnij nacisnąć F4i wejść Microsoft.Win32
na karcie Import przestrzeni nazw. W programie Visual Studio potrzebujesz using Microsoft.Win32;
górnej części kodu.
Porada: Aby zapoznać się z nowymi operatorami obsługi wartości null , wypróbuj (i debuguj) następujący kod w LinqPad:
Przykład 3: Demonstracja operatorów obsługi wartości 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>"
}
Spróbuj tego ze skrzypcami .Net
Jeśli jesteś zainteresowany, oto kilka przykładów, które zebrałem, pokazując, co jeszcze możesz zrobić za pomocą tego narzędzia.