Masih ada dukungan asli untuk akses registri di bawah 64 bit Windows menggunakan Framework 4.x . Kode berikut diuji dengan Windows 7, 64 bit dan juga dengan Windows 10, 64 bit .
Alih-alih menggunakan "Wow6432Node"
, yang mengemulasi node dengan memetakan satu pohon registri ke yang lain sehingga muncul di sana secara virtual, Anda dapat melakukan berikut ini:
Putuskan, apakah Anda perlu mengakses registri 64 bit atau 32 bit, dan gunakan seperti yang dijelaskan di bawah ini. Anda juga dapat menggunakan kode yang saya sebutkan nanti (bagian Informasi tambahan), yang membuat kueri gabungan untuk mendapatkan kunci registri dari kedua node dalam satu kueri - jadi Anda masih dapat menanyakannya dengan menggunakan jalur sebenarnya.
Registri 64 bit
Untuk mengakses registri 64 bit , Anda dapat menggunakan RegistryView.Registry64
sebagai berikut:
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));
Registri 32 bit
Jika Anda ingin mengakses registri 32bit , gunakan RegistryView.Registry32
sebagai berikut:
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));
Jangan bingung, kedua versi tersebut menggunakan Microsoft.Win32.RegistryHive.LocalMachine
sebagai parameter pertama, Anda membuat perbedaan apakah akan menggunakan 64 bit atau 32 bit dengan parameter ke - 2 ( RegistryView.Registry64
versus RegistryView.Registry32
).
Catat itu
Pada Windows 64 bit, HKEY_LOCAL_MACHINE\Software\Wow6432Node
berisi nilai yang digunakan oleh aplikasi 32 bit yang berjalan pada sistem 64 bit. Hanya aplikasi 64 bit yang benar yang menyimpan nilainya HKEY_LOCAL_MACHINE\Software
secara langsung. Subpohon Wow6432Node
sepenuhnya transparan untuk aplikasi 32 bit, aplikasi 32 bit masih terlihat HKEY_LOCAL_MACHINE\Software
seperti yang diharapkan (ini semacam pengalihan). Pada versi Windows yang lebih lama dan juga Windows 7 32 bit (dan Vista 32 bit) subpohon tersebut Wow6432Node
jelas tidak ada.
Karena bug di Windows 7 (64 bit), versi kode sumber 32 bit selalu mengembalikan "Microsoft" terlepas dari organisasi mana yang telah Anda daftarkan sementara versi kode sumber 64 bit mengembalikan organisasi yang benar.
Kembali ke contoh yang Anda berikan, lakukan dengan cara berikut untuk mengakses cabang 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");
Informasi tambahan - untuk penggunaan praktis:
Saya ingin menambahkan pendekatan menarik yang disarankan Johny Skovdal dalam komentar, yang saya ambil untuk mengembangkan beberapa fungsi berguna dengan menggunakan pendekatannya: Dalam beberapa situasi Anda ingin mendapatkan kembali semua kunci terlepas dari apakah itu 32 bit atau 64 bit. Nama contoh SQL adalah contohnya. Anda dapat menggunakan kueri gabungan dalam kasus tersebut sebagai berikut (C # 6 atau lebih tinggi):
// 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);
}
Sekarang Anda cukup menggunakan fungsi di atas sebagai berikut:
Contoh 1: Dapatkan nama instance 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}");
}
akan memberi Anda daftar nama dan nilai nilai di sqlRegPath.
Catatan: Anda dapat mengakses nilai default kunci (ditampilkan oleh alat baris perintah REGEDT32.EXE
sebagai (Default)
) jika Anda menghilangkan ValueName
parameter dalam fungsi terkait di atas.
Untuk mendapatkan daftar subkunci dalam kunci registri, gunakan fungsi GetRegKeyNames
atau GetAllRegKeyNames
. Anda dapat menggunakan daftar ini untuk menelusuri kunci lebih lanjut di registri.
Contoh 2: Dapatkan informasi uninstall perangkat lunak yang diinstal
var currentVersionRegPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion";
var uninstallRegPath = $@"{currentVersionRegPath}\Uninstall";
var regKeys = Registry.GetAllRegKeyNames(RegPath: uninstallRegPath);
akan mendapatkan semua kunci uninstall 32 bit dan 64 bit.
Perhatikan penanganan null yang diperlukan dalam fungsi karena SQL server dapat diinstal sebagai 32 bit atau 64 bit (Contoh 1 di atas). Fungsinya kelebihan beban sehingga Anda masih dapat meneruskan parameter 32 bit atau 64 bit jika diperlukan - namun, jika Anda menghilangkannya maka ia akan mencoba membaca 64 bit, jika gagal (nilai null), ia membaca nilai 32 bit.
Ada satu kekhususan di sini: Karena GetAllRegValueNames
biasanya digunakan dalam konteks perulangan (lihat Contoh 1 di atas), ia mengembalikan enumerabel kosong daripada null
menyederhanakan foreach
perulangan: jika tidak ditangani seperti itu, perulangan harus diawali dengan sebuah if
pemeriksaan pernyataan untuk null
yang akan menjadi rumit karena harus melakukan itu - sehingga yang ditangani sekali dalam fungsi.
Mengapa repot-repot tentang null? Karena jika Anda tidak peduli, Anda akan lebih pusing mencari tahu mengapa pengecualian referensi nol itu dimasukkan ke dalam kode Anda - Anda akan menghabiskan banyak waktu untuk mencari tahu di mana dan mengapa hal itu terjadi. Dan jika itu terjadi dalam produksi, Anda akan sangat sibuk mempelajari file log atau log peristiwa (saya harap Anda telah menerapkan logging) ... lebih baik hindari masalah null di mana Anda bisa dengan cara defensif. Operator ?.
, ?[
... ]
dan ??
dapat banyak membantu Anda (lihat kode yang disediakan di atas). Ada artikel terkait yang bagus membahas jenis referensi nullable baru di C # , yang saya sarankan untuk dibaca dan juga yang ini tentang operator Elvis.
Petunjuk: Anda dapat menggunakan edisi gratis Linqpad untuk menguji semua contoh pada Windows. Itu tidak membutuhkan instalasi. Jangan lupa untuk menekan F4dan masuk Microsoft.Win32
di tab impor Namespace. Dalam Visual Studio, Anda memerlukan using Microsoft.Win32;
di bagian atas kode Anda.
Tip: Untuk membiasakan diri Anda dengan operator penanganan null baru , coba (dan debug) kode berikut di LinqPad:
Contoh 3: Mendemonstrasikan operator penanganan 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>"
}
Cobalah dengan biola .Net
Jika Anda tertarik, berikut beberapa contoh yang saya kumpulkan untuk menunjukkan apa lagi yang dapat Anda lakukan dengan alat tersebut.