Dav*_*ner 91 .net c# registry 64-bit 32-bit
我有为AnyCPU编译的ac#单元测试项目.我们的构建服务器是64位机器,并安装了64位SQL Express实例.
测试项目使用类似于以下内容的代码来标识.MDF文件的路径:
private string GetExpressPath()
{
RegistryKey sqlServerKey = Registry.LocalMachine.OpenSubKey( @"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL" );
string sqlExpressKeyName = (string) sqlServerKey.GetValue( "SQLEXPRESS" );
RegistryKey sqlInstanceSetupKey = sqlServerKey.OpenSubKey( sqlExpressKeyName + @"\Setup" );
return sqlInstanceSetupKey.GetValue( "SQLDataRoot" ).ToString();
}
Run Code Online (Sandbox Code Playgroud)
这段代码在我们的32位工作站上工作正常,并且在我最近使用NCover启用代码覆盖率分析之前,在构建服务器上工作正常.因为NCover使用32位COM组件,所以测试运行器(Gallio)作为32位进程运行.
检查注册表,下面没有"实例名称"键
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SQL Server
在32位模式下运行的应用程序是否有办法访问Wow6432Node外部的注册表?
Mat*_*att 140
使用.NET Framework 4.x在64位Windows下仍然支持注册表访问.以下代码使用 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();
localKey.Close();
}
Console.WriteLine(String.Format("RegisteredOrganization [value64]: {0}",value64));
Run Code Online (Sandbox Code Playgroud)
如果要访问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();
localKey32.Close();
}
Console.WriteLine(String.Format("RegisteredOrganization [value32]: {0}",value32));
Run Code Online (Sandbox Code Playgroud)
不要混淆,这两个版本使用的是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");
Run Code Online (Sandbox Code Playgroud)
其他实用信息:
我想在评论中添加一个有趣的方法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)?.G??etValueNames();
}
public static IEnumerable<string> GetAllRegValueNames(string RegPath,
RegistryHive hive = RegistryHive.LocalMachine)
{
var reg64 = GetRegValueNames(RegistryView.Registry64, RegPath, hive);
var reg32 = GetRegValueNames(RegistryView.Re??gistry32, 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)?.G??etValue(ValueName);
}
public static object GetRegValue(string RegPath, string ValueName="",
RegistryHive hive = RegistryHive.LocalMachine)
{
return GetRegValue(RegistryView.Registry64, RegPath, ValueName, hive)
?? GetRegValue(RegistryView.Re??gistry32, 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.Re??gistry32, RegPath, hive);
var result = (reg64 != null && reg32 != null) ? reg64.Union(reg32) : (reg64 ?? reg32);
return (result ?? new List<string>().AsEnumerable()).OrderBy(x => x);
}
Run Code Online (Sandbox Code Playgroud)
现在您可以简单地使用上面的函数,如下所示:
示例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}");
}
Run Code Online (Sandbox Code Playgroud)
将为您提供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);
Run Code Online (Sandbox Code Playgroud)
将获得所有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>"
}
Run Code Online (Sandbox Code Playgroud)
如果你有兴趣,这里有一些例子,我把它们放在一起,展示你可以用这个工具做些什么.
我没有足够的回复评论,但值得指出的是,它在使用OpenRemoteBaseKey打开远程注册表时有效.添加RegistryView.Registry64参数允许机器A上的32位程序访问机器B上的64位注册表.在我传递该参数之前,我的程序在OpenRemoteBaseKey之后读取了32位,并且没有找到密钥I之后.
注意:在我的测试中,远程计算机实际上是我的计算机,但我通过OpenRemoteBaseKey访问它,就像我对不同的计算机一样.
归档时间: |
|
查看次数: |
60078 次 |
最近记录: |