对于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