Hiện vẫn còn hỗ trợ cho truy xuất registry dưới Windows 64 bit sử dụng .NET Framework 4.x . Đoạn mã sau được thử nghiệm với Windows 7, 64 bit và cả Windows 10, 64 bit .
Thay vì sử dụng "Wow6432Node"
, mô phỏng một nút bằng cách ánh xạ một cây đăng ký này vào một cây đăng ký khác làm cho nó xuất hiện ở đó hầu như, bạn có thể thực hiện theo cách sau:
Quyết định xem bạn cần truy cập sổ đăng ký 64 bit hay 32 bit và sử dụng nó như được mô tả bên dưới. Bạn cũng có thể sử dụng mã tôi đã đề cập sau (phần Thông tin bổ sung), mã này tạo truy vấn liên hợp để lấy khóa đăng ký từ cả hai nút trong một truy vấn - vì vậy bạn vẫn có thể truy vấn chúng bằng cách sử dụng đường dẫn thực của chúng.
Đăng ký 64 bit
Để truy cập sổ đăng ký 64 bit , bạn có thể sử dụng RegistryView.Registry64
như sau:
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));
Đăng ký 32 bit
Nếu bạn muốn truy cập sổ đăng ký 32 bit , hãy sử dụng RegistryView.Registry32
như sau:
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));
Đừng nhầm lẫn, cả hai phiên bản đều đang sử dụng Microsoft.Win32.RegistryHive.LocalMachine
làm tham số đầu tiên, bạn phân biệt xem nên sử dụng 64 bit hay 32 bit bằng tham số thứ 2 ( RegistryView.Registry64
so với RegistryView.Registry32
).
Lưu ý rằng
Trên Windows 64 bit, HKEY_LOCAL_MACHINE\Software\Wow6432Node
chứa các giá trị được sử dụng bởi các ứng dụng 32 bit chạy trên hệ thống 64 bit. Chỉ các ứng dụng 64 bit thực sự mới lưu trữ HKEY_LOCAL_MACHINE\Software
trực tiếp các giá trị của chúng . Cây con Wow6432Node
hoàn toàn trong suốt đối với các ứng dụng 32 bit, các ứng dụng 32 bit vẫn nhìn thấy HKEY_LOCAL_MACHINE\Software
như họ mong đợi (nó là một loại chuyển hướng). Trong các phiên bản Windows cũ hơn cũng như Windows 7 32 bit (và Vista 32 bit), cây con Wow6432Node
rõ ràng là không tồn tại.
Do một lỗi trong Windows 7 (64 bit), phiên bản mã nguồn 32 bit luôn trả về "Microsoft" bất kể bạn đã đăng ký tổ chức nào trong khi phiên bản mã nguồn 64 bit trả về đúng tổ chức.
Quay lại ví dụ bạn đã cung cấp, hãy thực hiện theo cách sau để truy cập nhánh 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");
Thông tin bổ sung - để sử dụng thực tế:
Tôi muốn thêm một cách tiếp cận thú vị mà Johny Skovdal đã đề xuất trong các nhận xét, mà tôi đã chọn để phát triển một số chức năng hữu ích bằng cách sử dụng cách tiếp cận của anh ấy: Trong một số tình huống, bạn muốn lấy lại tất cả các khóa bất kể nó là 32 bit hay 64 bit. Các tên phiên bản SQL là một ví dụ. Bạn có thể sử dụng truy vấn liên hợp trong trường hợp đó như sau (C # 6 trở lên):
// 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);
}
Bây giờ bạn có thể chỉ cần sử dụng các chức năng trên như sau:
Ví dụ 1: Lấy tên phiên bản 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}");
}
sẽ cung cấp cho bạn danh sách tên giá trị và giá trị trong sqlRegPath.
Lưu ý: Bạn có thể truy cập giá trị mặc định của một khóa (được hiển thị bởi công cụ dòng lệnh REGEDT32.EXE
dưới dạng (Default)
) nếu bạn bỏ qua ValueName
tham số trong các chức năng tương ứng ở trên.
Để nhận danh sách các SubKeys trong khóa đăng ký, hãy sử dụng hàm GetRegKeyNames
hoặc GetAllRegKeyNames
. Bạn có thể sử dụng danh sách này để duyệt qua các khóa khác trong sổ đăng ký.
Ví dụ 2: Lấy thông tin gỡ cài đặt của phần mềm đã cài đặt
var currentVersionRegPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion";
var uninstallRegPath = $@"{currentVersionRegPath}\Uninstall";
var regKeys = Registry.GetAllRegKeyNames(RegPath: uninstallRegPath);
sẽ nhận được tất cả các khóa gỡ cài đặt 32 bit và 64 bit.
Lưu ý xử lý null được yêu cầu trong các hàm vì máy chủ SQL có thể được cài đặt dưới dạng 32 bit hoặc 64 bit (Ví dụ 1 ở trên). Các hàm bị quá tải nên bạn vẫn có thể truyền tham số 32 bit hoặc 64 bit nếu được yêu cầu - tuy nhiên, nếu bạn bỏ qua nó thì nó sẽ cố đọc 64 bit, nếu không thành công (giá trị null), nó sẽ đọc các giá trị 32 bit.
Có một điểm đặc biệt ở đây: Vì GetAllRegValueNames
thường được sử dụng trong ngữ cảnh vòng lặp (xem Ví dụ 1 ở trên), nó trả về một kiểu liệt kê trống thay vì null
đơn giản hóa foreach
các vòng lặp: nếu nó không được xử lý theo cách đó, vòng lặp sẽ phải có tiền tố là một if
câu lệnh kiểm tra null
cái nào sẽ rất phức tạp khi phải làm điều đó - để điều đó được xử lý một lần trong hàm.
Tại sao phải bận tâm về null? Bởi vì nếu bạn không quan tâm, bạn sẽ phải đau đầu hơn rất nhiều khi tìm ra lý do tại sao ngoại lệ tham chiếu rỗng đó lại được đưa vào mã của bạn - bạn sẽ mất rất nhiều thời gian để tìm ra vị trí và lý do nó xảy ra. Và nếu nó xảy ra trong quá trình sản xuất, bạn sẽ rất bận rộn với việc nghiên cứu các tệp nhật ký hoặc nhật ký sự kiện (tôi hy vọng bạn đã triển khai ghi nhật ký) ... tốt hơn hãy tránh các vấn đề vô hiệu khi bạn có thể theo cách phòng thủ. Các nhà khai thác ?.
, ?[
... ]
và ??
có thể giúp bạn rất nhiều (xem đoạn mã được cung cấp ở trên). Có một bài viết liên quan rất hay thảo luận về các kiểu tham chiếu nullable mới trong C # mà tôi khuyên bạn nên đọc và cả bài viết này về toán tử Elvis.
Gợi ý: Bạn có thể sử dụng phiên bản Linqpad miễn phí để kiểm tra tất cả các ví dụ trong Windows. Nó không yêu cầu cài đặt. Đừng quên nhấn F4và nhập Microsoft.Win32
vào tab nhập Không gian tên. Trong Visual Studio, bạn yêu cầu using Microsoft.Win32;
ở đầu mã của mình.
Mẹo: Để tự làm quen với các toán tử xử lý null mới , hãy thử (và gỡ lỗi) mã sau trong LinqPad:
Ví dụ 3: Trình bày các toán tử xử lý 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>"
}
Hãy thử nó với .Net fiddle
Nếu bạn quan tâm, đây là một số ví dụ tôi tổng hợp cho thấy bạn có thể làm gì khác với công cụ này.