對於64位Windows下的註冊表訪問,仍然使用.NET Framework 4.x。以下代碼使用 Windows 7,64位 以及 Windows 10,64位進行測試。 要訪問64位註冊表,你可以使用:
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();
}
Console.WriteLine(String.Format("RegisteredOrganization [value64]: {0}",value64));
如果您要訪問的32位註冊表,用途:
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();
}
Console.WriteLine(String.Format("RegisteredOrganization [value32]: {0}",value32));
不要被迷惑,兩個版本使用Microsoft.Win32.RegistryHive.LocalMachine
作爲第一個參數,可以區分是使用64位還是32位由第2參數(RegistryView.Registry64
與RegistryView.Registry32
)。
注意該
在64位Windows,HKEY_LOCAL_MACHINE\Software\Wow6432Node
包含由64位系統上運行32個應用程序使用的值。只有真正的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已在評論中提出,我已經選擇使用他的方法來開發一些有用的功能:在某些情況下,您可以nt來取回所有密鑰,不管它是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);
}
現在,你可以簡單地使用上述功能如下:
var [email protected]"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL";
foreach (var valueName in GetAllRegValueNames(sqlRegPath))
{
var value=GetRegValue(sqlRegPath, valueName);
Console.WriteLine($"{valueName}={value}");
}
,這將給你一個列表sqlRegPath中的值名稱和值。
注意函數中需要空處理,因爲SQL Server可以安裝爲32位或64位。函數被重載,所以如果需要的話你仍然可以傳遞32位或64位參數 - 但是,如果你省略了它,它將嘗試讀取64位,如果失敗(空值),它讀取32位值。
有一個專門在這裏:因爲GetAllRegValueNames
在一個循環背景下通常使用(見上面的例子),它返回一個空的枚舉,而不是null
簡化foreach
循環:如果不處理這種方式,循環必須以if
語句作爲前綴,檢查null
,這樣做會很麻煩 - 所以在函數中處理一次。
爲什麼要打擾null?因爲如果你不在意,你會有更多的頭痛發現爲什麼在你的代碼中拋出空引用異常 - 你會花很多時間來找出它發生的地方和原因。如果它發生在生產環境中,你將會非常忙於學習日誌文件或事件日誌(我希望你已經實現了日誌記錄功能)......在防禦方式下更好地避免空問題。運營商?.
,?[
... ]
和??
可以幫助您很多(請參閱上面提供的代碼)。
提示:您可以使用Linqpad免費版本來測試Windows下所有的例子。它不需要安裝。不要忘記按F4並在名稱空間導入選項卡中輸入Microsoft.Win32
。在Visual Studio中,您需要代碼頂部的using Microsoft.Win32;
。
提示:爲了與新空處理運營商熟悉,嘗試(和調試)在LinqPad下面的代碼:
string[] test { get { return null;} } // property used to return null
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>"
}
如果你有興趣,here一些我把這些例子放在一起展示了你可以用這個工具做些什麼。
謝謝你提供的全面的答案。從內存中,我想我在發佈這個問題時使用了.NET 3.5,但很高興看到.NET 4改善了這種情況 – 2012-11-06 00:03:49