ยังคงมีการสนับสนุนพื้นเมืองสำหรับการเข้าถึงรีจิสทรีภายใต้ 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 บิตโดยพารามิเตอร์ที่ 2 ( RegistryView.Registry64
เทียบกับRegistryView.Registry32
)
โปรดทราบว่า
บน Windows 64 บิตHKEY_LOCAL_MACHINE\Software\Wow6432Node
ประกอบด้วยค่าที่ใช้โดยแอปพลิเคชัน 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");
ข้อมูลเพิ่มเติม - สำหรับการใช้งานจริง:
ฉันต้องการเพิ่มแนวทางที่น่าสนใจที่Johny Skovdalได้แนะนำไว้ในความคิดเห็นซึ่งฉันได้หยิบขึ้นมาเพื่อพัฒนาฟังก์ชันที่มีประโยชน์โดยใช้แนวทางของเขา: ในบางสถานการณ์คุณต้องการเรียกคืนคีย์ทั้งหมดไม่ว่าจะเป็น 32 บิตหรือ 64 บิต ชื่ออินสแตนซ์ SQL เป็นตัวอย่าง คุณสามารถใช้คิวรีแบบร่วมในกรณีนั้นได้ดังนี้ (C # 6 หรือสูงกว่า):
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
พารามิเตอร์ในฟังก์ชันที่เกี่ยวข้องด้านบน
หากต้องการรับรายการSubKeysภายในคีย์รีจิสทรีให้ใช้ฟังก์ชันGetRegKeyNames
หรือGetAllRegKeyNames
. คุณสามารถใช้รายการนี้เพื่อสำรวจคีย์เพิ่มเติมในรีจิสทรี
ตัวอย่างที่ 2: รับข้อมูลการถอนการติดตั้งของซอฟต์แวร์ที่ติดตั้ง
var currentVersionRegPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion";
var uninstallRegPath = $@"{currentVersionRegPath}\Uninstall";
var regKeys = Registry.GetAllRegKeyNames(RegPath: uninstallRegPath);
จะได้รับคีย์ถอนการติดตั้ง 32 บิตและ 64 บิตทั้งหมด
โปรดสังเกตว่าจำเป็นต้องมีการจัดการ nullในฟังก์ชันเนื่องจากเซิร์ฟเวอร์ SQL สามารถติดตั้งเป็น 32 บิตหรือ 64 บิต (ตัวอย่างที่ 1 ด้านบน) ฟังก์ชั่นมีการโหลดมากเกินไปดังนั้นคุณยังสามารถส่งผ่านพารามิเตอร์ 32 บิตหรือ 64 บิตได้หากจำเป็น - อย่างไรก็ตามหากคุณละเว้นมันจะพยายามอ่าน 64 บิตหากล้มเหลว (ค่า null) จะอ่านค่า 32 บิต
มีความพิเศษอย่างหนึ่งที่นี่: เนื่องจากGetAllRegValueNames
โดยปกติจะใช้ในบริบทการวนซ้ำ (ดูตัวอย่างที่ 1 ด้านบน) จะส่งคืนค่าว่างที่แจกแจงได้แทนที่จะnull
ทำให้foreach
ลูปง่ายขึ้น: หากไม่ได้รับการจัดการด้วยวิธีนี้การวนซ้ำจะต้องนำหน้าด้วย การif
ตรวจสอบคำสั่งnull
ซึ่งจะยุ่งยากหากต้องทำเช่นนั้น - เพื่อจัดการกับครั้งเดียวในฟังก์ชัน
ทำไมต้องกังวลเกี่ยวกับ null? เพราะถ้าคุณไม่สนใจคุณจะต้องปวดหัวมากขึ้นในการค้นหาว่าเหตุใดข้อยกเว้นการอ้างอิงที่เป็นโมฆะจึงถูกส่งเข้ามาในโค้ดของคุณคุณจะต้องใช้เวลามากมายในการค้นหาว่ามันเกิดขึ้นที่ไหนและทำไม และหากเกิดขึ้นในการใช้งานจริงคุณจะยุ่งมากกับการศึกษาไฟล์บันทึกหรือบันทึกเหตุการณ์ (ฉันหวังว่าคุณจะนำการบันทึกมาใช้) ... ดีกว่าหลีกเลี่ยงปัญหาว่างที่คุณสามารถป้องกันได้ ผู้ประกอบการ?.
, ?[
... ]
และ??
สามารถช่วยให้คุณมาก (ดูรหัสที่ให้ไว้ด้านบน) มีบทความที่เกี่ยวข้องที่ดีเกี่ยวกับประเภทการอ้างอิงที่เป็นโมฆะใหม่ใน C #ซึ่งฉันแนะนำให้อ่านและบทความนี้เกี่ยวกับตัวดำเนินการ Elvis
คำแนะนำ:คุณสามารถใช้Linqpadรุ่นฟรีเพื่อทดสอบตัวอย่างทั้งหมดใน Windows ไม่จำเป็นต้องติดตั้ง อย่าลืมกดF4เข้าไปMicrosoft.Win32
ในแท็บนำเข้าเนมสเปซ ใน Visual Studio คุณต้องการusing Microsoft.Win32;
ที่ด้านบนของโค้ดของคุณ
เคล็ดลับ:การทำความคุ้นเคยกับใหม่ผู้ประกอบการจัดการ null ,ลอง (และการแก้ปัญหา) รหัสต่อไปนี้ใน LinqPad:
ตัวอย่างที่ 3: การสาธิตตัวดำเนินการจัดการกับค่าว่าง
static string[] test { get { return null;} }
static void Main()
{
test.Dump();
test?.Dump();
test?[0].Dump();
(test?[0]).Dump();
(test?[0]??"<null>").Dump();
}
ลองใช้กับ. Net fiddle
หากคุณสนใจนี่คือตัวอย่างบางส่วนที่ฉันรวบรวมไว้ซึ่งแสดงให้เห็นว่าคุณสามารถใช้เครื่องมือนี้ทำอะไรได้อีกบ้าง