Існує ще нативная підтримка доступу реєстру в 64 - розрядної ОС Windows з використанням .NET Framework 4.x . Наступний код тестується з Windows 7, 64 біт, а також з Windows 10, 64 біт .
Замість використання "Wow6432Node"
, яке емулює вузол, перекладаючи одне дерево реєстру в інше, роблячи його віртуальним, ви можете виконати наступне:
Вирішіть, чи потрібен вам доступ до 64-розрядного або 32-розрядного реєстру, і використовуйте його, як описано нижче. Ви також можете використовувати код, про який я згадав пізніше (розділ "Додаткова інформація"), який створює запит об'єднання для отримання ключів реєстру від обох вузлів в одному запиті - так що ви все одно можете запитувати їх, використовуючи їх реальний шлях.
64-розрядний реєстр
Щоб отримати доступ до 64-розрядного реєстру , ви можете використовувати RegistryView.Registry64
наступне:
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));
32-розрядний реєстр
Якщо ви хочете отримати доступ до 32-бітного реєстру , використовуйте RegistryView.Registry32
наступне:
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));
Не плутайте, обидві версії використовуються Microsoft.Win32.RegistryHive.LocalMachine
як перший параметр; ви робите різницю між тим, чи використовувати 64-бітну або 32-бітну версію для другого параметра ( RegistryView.Registry64
проти RegistryView.Registry32
).
Зауважте, що
У 64- HKEY_LOCAL_MACHINE\Software\Wow6432Node
бітовій Windows містить значення, що використовуються 32-розрядними програмами, що працюють у 64-розрядної системі. Тільки справжні 64-розрядні програми зберігають свої значення HKEY_LOCAL_MACHINE\Software
безпосередньо. Піддерево Wow6432Node
є повністю прозорим для 32-розрядних програм, 32-розрядні програми все ще бачать, HKEY_LOCAL_MACHINE\Software
як вони очікують (це свого роду переспрямування). У старих версіях Windows, а також 32-розрядної Windows 7 (і Vista 32-розрядної) піддерева, Wow6432Node
очевидно, не існує.
Через помилку в Windows 7 (64-розрядна версія), 32-розрядна версія вихідного коду завжди повертає "Microsoft", незалежно від того, яку організацію ви зареєстрували, тоді як 64-розрядна версія вихідного коду повертає потрібну організацію.
Повертаючись до прикладу, який ви надали, зробіть це таким чином, щоб отримати доступ до 64-бітової гілки:
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");
Додаткова інформація - для практичного використання:
Я хотів би додати цікавий підхід , запропонований Джоні Сковдалем у коментарях, який я підібрав для розробки деяких корисних функцій, використовуючи його підхід: У деяких ситуаціях ви хочете повернути всі ключі, незалежно від того, чи є вони 32-бітними чи 64 біт. Прикладом є назви екземплярів SQL. Ви можете використовувати запит об'єднання в такому випадку наступним чином (C # 6 або вище):
// 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);
}
Тепер ви можете просто використовувати наведені вище функції наступним чином:
Приклад 1: Отримайте імена екземплярів 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}");
}
надасть вам список імен значень та значень у sqlRegPath.
Примітка: Ви можете отримати доступ до значення ключа за замовчуванням (відображається інструментом командного рядка REGEDT32.EXE
як (Default)
), якщо пропустити ValueName
параметр у відповідних функціях вище.
Щоб отримати список підключів у розділі реєстру, використовуйте функцію GetRegKeyNames
або GetAllRegKeyNames
. Ви можете використовувати цей список для перегляду подальших ключів у реєстрі.
Приклад 2: Отримайте інформацію про видалення встановленого програмного забезпечення
var currentVersionRegPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion";
var uninstallRegPath = $@"{currentVersionRegPath}\Uninstall";
var regKeys = Registry.GetAllRegKeyNames(RegPath: uninstallRegPath);
отримає всі 32-розрядні та 64-розрядні ключі видалення.
Зверніть увагу на необхідну обробку функцій, оскільки SQL-сервер можна встановити як 32-розрядний або як 64-розрядний (Приклад 1 вище). Функції перевантажені, тому ви все одно можете передавати 32-бітний або 64-бітний параметр, якщо потрібно - однак, якщо його опустити, він спробує прочитати 64-бітний, якщо це не вдається (нульове значення), він зчитує 32-бітні значення.
Тут є одна спеціальність: оскільки GetAllRegValueNames
зазвичай використовується в контексті циклу (див. Приклад 1 вище), він повертає порожнє перелічуване, а не null
для спрощення foreach
циклів: якщо він не буде оброблятися таким чином, цикл повинен мати префікс if
перевірка особистих даних для null
яких буде обтяжливою необхідності зробити це - так , що розглядається один раз в функції.
Чому турбуватися про нуль? Тому що якщо вас не хвилює, у вас буде набагато більше головних болів, з'ясувавши, чому цей нульовий винятковий виняток був кинутий у ваш код - ви витратите багато часу, щоб дізнатися, де і чому це сталося. І якщо це сталося у виробництві, ви будете дуже зайняті вивченням файлів журналів або журналів подій (сподіваюсь, у вас введено ведення журналу) ... краще уникайте нульових проблем, де ви можете захисним способом. Оператори ?.
, ?[
... ]
і ??
можуть вам дуже допомогти (див. Наведений вище код). Є приємна пов’язана стаття, де обговорюються нові типи посилань , що дозволяють обнулятись, в C # , яку я рекомендую прочитати, а також ця про оператор Елвіса.
Підказка: Ви можете використовувати безкоштовну версію Linqpad для тестування всіх прикладів під Windows. Це не вимагає установки. Не забудьте натиснути F4та ввести Microsoft.Win32
на вкладці імпорту простору імен. У Visual Studio потрібно using Microsoft.Win32;
вгорі коду.
Порада. Щоб ознайомитися з новими операторами обробки нуля , спробуйте (та налагодьте) такий код у LinqPad:
Приклад 3: Демонстрація операторів обробки нуля
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>"
}
Спробуйте за допомогою .Net fiddle
Якщо вам цікаво, ось кілька прикладів, які я зібрав, показуючи, що ще можна зробити за допомогою цього інструменту.