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.
Saya tidak memiliki cukup perwakilan untuk berkomentar, tetapi perlu ditunjukkan bahwa ini berfungsi saat membuka registri jarak jauh menggunakan OpenRemoteBaseKey. Menambahkan parameter RegistryView.Registry64 memungkinkan program 32-bit pada Mesin A untuk mengakses registri 64-bit pada Mesin B. Sebelum saya meneruskan parameter itu, program saya membaca 32-bit setelah OpenRemoteBaseKey, dan tidak menemukan kunci I adalah setelah.
Catatan: Dalam pengujian saya, mesin jarak jauh sebenarnya adalah mesin saya, tetapi saya mengaksesnya melalui OpenRemoteBaseKey, seperti yang saya lakukan untuk mesin lain.
sumber
coba ini (dari proses 32bit):
(menemukannya di sini ).
sumber
reg.exe /?
untuk mendapatkan info lebih lanjut ...Jika Anda tidak dapat menggunakan .NET 4 dengan itu
RegistryKey.OpenBaseKey(..., RegistryView.Registry64)
, Anda perlu menggunakan Windows API secara langsung.Interop minimalnya seperti:
Gunakan seperti:
sumber
Dari apa yang telah saya baca dan dari pengujian saya sendiri, menurut saya registri harus diperiksa di jalur ini "SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall". Karena di jalur lain register tidak dihapus setelah menghapus program.
Dengan cara ini saya mendapat 64 register dengan konfigurasi 32 bit.
Untuk 32 register adalah:
sumber