在使用.NET Framework 4.x的 64位Windows下,仍对注册表访问提供本机支持。以下代码已在 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
用作第一个参数,您通过第二个参数(vs )来区分使用64位还是32位。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在评论中建议了该方法,我通过他的方法选择了该方法来开发一些有用的功能:在某些情况下,无论32位还是32位,您都希望获取所有密钥。 64位。SQL实例名称就是这样的示例。在这种情况下,您可以按以下方式使用联合查询(C#6或更高版本):
// 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);
}
现在,您可以简单地使用上述功能,如下所示:
示例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
。
为了得到列表的子项注册表项中,使用功能GetRegKeyNames
或GetAllRegKeyNames
。您可以使用此列表遍历注册表中的其他项。
示例2:获取已安装软件的卸载信息
var currentVersionRegPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion";
var uninstallRegPath = $@"{currentVersionRegPath}\Uninstall";
var regKeys = Registry.GetAllRegKeyNames(RegPath: uninstallRegPath);
将获得所有32位和64位卸载密钥。
请注意函数中所需的空处理,因为SQL Server可以安装为32位或64位(上面的示例1)。这些函数已重载,因此您仍然可以根据需要传递32位或64位参数-但是,如果省略它,则它将尝试读取64位,如果失败(空值),它将读取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;} } // 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>"
}
用.Net小提琴试试
如果你有兴趣,这里有一些例子我放在一起展示你可以用工具做什么。