从32位应用程序读取64位注册表

我有一个为AnyCPU编译的c#单元测试项目。我们的构建服务器是一个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();
    }

此代码在我们的32位工作站上工作正常,并且在构建服务器上工作正常,直到我最近启用了与NCover的代码覆盖率分析。由于NCover使用32位COM组件,测试运行器(Gallio)以32位进程运行。

检查注册表,没有”Instance Names”键

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SQL Server

有没有办法在32位模式下运行的应用程序访问Wow6432Node之外的注册表?

最佳解决方案

在创建/打开注册表项时,必须使用KEY_WOW64_64KEY参数。但是,AFAIK对于注册表类是不可能的,但只能直接使用API​​。

This可能有助于您开始使用。

次佳解决方案

仍然使用.NET Framework 4.x在64位Windows下仍然支持注册表访问。以下代码通过Windows 7 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作为第一个参数,您可以区分第二个参数(RegistryView.Registry64RegistryView.Registry32)是否使用64位或32位。

注意

  • 在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");

提示:您可以使用Linqpad来测试Windows 7下的所有示例。它不需要安装。

发表评论