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

时间:2022-07-01 22:35:37

I have a c# unit test project that is compiled for AnyCPU. Our build server is a 64bit machine, and has a 64bit SQL Express instance installed.

我有一个为任何cpu编译的c#单元测试项目。我们的构建服务器是一个64位的机器,并安装了一个64位的SQL Express实例。

The test project uses code similar to the following to identify the path to the .MDF files:

测试项目使用与以下代码类似的代码来标识.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();
    }

This code works fine on our 32bit workstations, and did work ok on the build server until I recently enabled code coverage analysis with NCover. Because NCover uses a 32bit COM component, the test runner (Gallio) runs as a 32bit process.

这段代码在32位工作站中运行良好,并且在构建服务器上运行良好,直到最近启用了NCover的代码覆盖率分析。由于NCover使用了一个32位的COM组件,测试运行器(Gallio)运行为一个32位的进程。

Checking the registry, there is no "Instance Names" key under

检查注册表,下面没有“实例名”键。

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SQL Server

微软HKEY_LOCAL_MACHINE \ SOFTWARE \ Wow6432Node \ \ Microsoft SQL Server

Is there a way for an application running in 32bit mode to access the registry outside Wow6432Node?

是否有一种方法可以让应用程序以32位模式运行,以访问wow6432节点之外的注册表?

5 个解决方案

#1


16  

you have to use the KEY_WOW64_64KEY param when creating/opening the registry key. But AFAIK that's not possible with the Registry class but only when using the API directly.

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

This might help to get you started.

这可能会帮助你开始。

#2


109  

There is still native support for registry access under 64 bit Windows using .NET Framework 4.x. The following code is tested with  Windows 7, 64 bit  and also with  Windows 10, 64 bit. To access the 64 bit registry, you can use:

在使用。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(); 
} 
Console.WriteLine(String.Format("RegisteredOrganization [value64]: {0}",value64));

If you want to access the 32bit registry, use:

如果您想访问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));

Don't be confused, both versions are using Microsoft.Win32.RegistryHive.LocalMachine as first parameter, you make the distinction whether to use 64 bit or 32 bit by the 2nd parameter (RegistryView.Registry64 versus RegistryView.Registry32).

不要混淆,两个版本都使用Microsoft.Win32.RegistryHive。LocalMachine作为第一个参数,您可以通过第二个参数(RegistryView)来区分是否使用64位或32位。Registry64和RegistryView.Registry32)。

Note that

请注意,

  • On a 64bit Windows, HKEY_LOCAL_MACHINE\Software\Wow6432Node contains values used by 32 bit applications running on the 64 bit system. Only true 64 bit applications store their values in HKEY_LOCAL_MACHINE\Software directly. The subtree Wow6432Node is entirely transparent for 32 bit applications, 32 bit applications still see HKEY_LOCAL_MACHINE\Software as they expect it (it is a kind of redirection). In older versions of Windows as well as 32 bit Windows 7 (and Vista 32 bit) the subtree Wow6432Node obviously does not exist.

    在64位Windows上,HKEY_LOCAL_MACHINE\Software\Wow6432Node包含32位运行在64位系统上的应用程序所使用的值。只有真正的64位应用程序可以直接在HKEY_LOCAL_MACHINE\软件中存储它们的值。子树Wow6432Node对于32位应用程序来说是完全透明的,32位应用程序仍然可以看到HKEY_LOCAL_MACHINE\软件(它是一种重定向)。在旧版本的Windows和32位Windows 7(和Vista 32位)中,子树Wow6432Node显然不存在。

  • Due to a bug in Windows 7 (64 bit), the 32 bit source code version always returns "Microsoft" regardless which organization you have registered while the 64 bit source code version returns the right organization.

    由于Windows 7(64位)中的一个错误,32位源代码版本总是返回“Microsoft”,不管您注册的是哪个组织,而64位源代码版本返回的是正确的组织。

Coming back to the example you've provided, do it the following way to access the 64 bit branch:

回到您提供的示例,使用以下方法访问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");

Update:

更新:

I'd like to add an interesting approach Johny Skovdal has suggested in the comments, which I've picked up to develop some useful functions by using his approach: In some situations you want to get back all keys regardless whether it is 32 bit or 64 bit. The SQL instance names are such an example. You can use a union query in that case as follows (C#6 or higher):

我想在评论中添加一个有趣的方法,我已经用他的方法开发了一些有用的函数:在某些情况下,无论它是32位还是64位,都需要返回所有的键。SQL实例名就是这样一个例子。在这种情况下,可以使用union查询(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);
}

Now you can simply use the functions above as follows:

现在您可以简单地使用上面的函数如下:

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}");
}

which will give you a list of the value names and values in sqlRegPath.

它将给出sqlRegPath中值名称和值的列表。

Note: You can access the default value of a key (displayed by the commandline tool REGEDT32.EXE as (Default)) if you omit the ValueName parameter in the corresponding functions above.

注意:您可以访问一个键的默认值(由命令行工具REGEDT32显示)。如果您在上面的相应函数中省略了ValueName参数,则EXE为(默认)。

Notice the null handling required in the functions because SQL server can be installed as 32 bit or as 64 bit. The functions are overloaded so you can still pass the 32 bit or 64 bit parameter if required - however, if you omit it then it will try to read 64 bit, if that fails (null value), it reads the 32 bit values.

注意在函数中需要的空处理,因为SQL server可以安装32位或64位。函数是重载的,因此如果需要,仍然可以传递32位或64位参数——但是,如果省略它,它将尝试读取64位,如果失败(空值),则读取32位值。

There is one speciality here: Because GetAllRegValueNames is usually used in a loop context (see example above), it returns an empty enumerable rather than null to simplify foreach loops: if it wouldn't be handled that way, the loop would have to be prefixed by an if statement checking for null which would be cumbersome having to do that - so that is dealt with once in the function.

这里有一个特色:因为GetAllRegValueNames通常是在一个循环中使用上下文(参见上面的例子),它将返回一个空可列举的而不是null来简化foreach循环:如果它不会这样处理,循环前缀必须由一个if语句检查null会麻烦不得不这么做——这是处理函数。

Why bothering about null? Because if you don't care, you'll have a lot more headaches finding out why that null reference exception was thrown in your code - you'd spend a lot of time finding out where and why it happened. And if it happened in production you'll be very busy studying log files or event logs (I hope you have logging implemented) ... better avoid null issues where you can in a defensive way. The operators ?., ?[...] and ?? can help you a lot (see the code provided above).

为什么困扰零呢?因为如果您不关心,您将会有更多的麻烦,找出为什么在您的代码中抛出了null引用异常—您将花费大量的时间找出它发生的原因和原因。如果它发生在生产中,您将非常忙碌地学习日志文件或事件日志(我希望您已经实现了日志记录)……最好避免用防守的方式解决问题。运营商吗?。?[…和? ?可以帮助您很多(参见上面提供的代码)。


Hint: You can use the free edition of Linqpad to test all examples under Windows. It doesn't require an installation. Don't forget to press F4 and enter Microsoft.Win32 in the Namespace import tab. In Visual Studio, you require using Microsoft.Win32; at the top of your code.

提示:您可以使用免费版的Linqpad来测试Windows下的所有示例。它不需要安装。别忘了按F4键进入微软。在名称空间导入选项卡中。在Visual Studio中,您需要使用Microsoft.Win32;在代码的顶部。

Tip: To familiarize yourself with the new null handling operators, try out (and debug) the following code in LinqPad:

提示:为了熟悉新的空处理操作符,请在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>"
}

If you're interested, here are some examples I put together showing what else you can do with the tool.

如果你感兴趣的话,这里有一些例子,我把它们放在一起,展示你可以用这个工具做些什么。

#3


4  

I don't have enough rep to comment, but it's worth pointing out that it works when opening a remote registry using OpenRemoteBaseKey. Adding the RegistryView.Registry64 parameter allows a 32-bit program on Machine A to access the 64-bit registry on Machine B. Before I passed that parameter, my program was reading the 32-bit after OpenRemoteBaseKey, and did not find the key I was after.

我没有足够的代表来评论,但值得指出的是,当使用OpenRemoteBaseKey打开远程注册表时,它是有效的。添加RegistryView。Registry64参数允许机器a上的32位程序在机器b*问64位注册表。在我传递这个参数之前,我的程序是在OpenRemoteBaseKey之后读取32位的,并且没有找到我要找的密钥。

Note: In my test, the remote machine was actually my machine, but I accessed it via OpenRemoteBaseKey, just as I would for a different machine.

注意:在我的测试中,远程机器实际上是我的机器,但是我通过OpenRemoteBaseKey访问它,就像我想换一台不同的机器一样。

#4


3  

If you cannot use .NET 4 with its RegistryKey.OpenBaseKey(..., RegistryView.Registry64), you need to use Windows API directly.

如果你不能使用。net 4的注册键。openbasekey(…,RegistryView.Registry64),您需要直接使用Windows API。

The minimal interop is like:

最小的互操作是:

internal enum RegistryFlags
{
    ...
    RegSz = 0x02,
    ...
    SubKeyWow6464Key = 0x00010000,
    ...
}

internal enum RegistryType
{
    RegNone = 0,
    ...
}

[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int RegGetValue(
    UIntPtr hkey, string lpSubKey, string lpValue, RegistryFlags dwFlags, 
    out RegistryType pdwType, IntPtr pvData, ref uint pcbData);

Use it like:

使用它:

IntPtr data = IntPtr.Zero;
RegistryType type;
uint len = 0;
RegistryFlags flags = RegistryFlags.RegSz | RegistryFlags.SubKeyWow6464Key;
UIntPtr key = (UIntPtr)((uint)RegistryHive.LocalMachine);

const string subkey= @"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL";
const string value = "SQLEXPRESS";

if (RegGetValue(key, subkey, value, flags, out type, data, ref len) == 0)
{
    data = Marshal.AllocHGlobal((int)len);
    if (RegGetValue(key, subkey, value, flags, out type, data, ref len) == 0)
    {
        string sqlExpressKeyName = Marshal.PtrToStringUni(data);
    }
}

#5


2  

try this (from a 32bit process):

试试这个(从一个32位的过程):

> %WINDIR%\sysnative\reg.exe query ...

(found that here).

(发现这里)。

#1


16  

you have to use the KEY_WOW64_64KEY param when creating/opening the registry key. But AFAIK that's not possible with the Registry class but only when using the API directly.

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

This might help to get you started.

这可能会帮助你开始。

#2


109  

There is still native support for registry access under 64 bit Windows using .NET Framework 4.x. The following code is tested with  Windows 7, 64 bit  and also with  Windows 10, 64 bit. To access the 64 bit registry, you can use:

在使用。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(); 
} 
Console.WriteLine(String.Format("RegisteredOrganization [value64]: {0}",value64));

If you want to access the 32bit registry, use:

如果您想访问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));

Don't be confused, both versions are using Microsoft.Win32.RegistryHive.LocalMachine as first parameter, you make the distinction whether to use 64 bit or 32 bit by the 2nd parameter (RegistryView.Registry64 versus RegistryView.Registry32).

不要混淆,两个版本都使用Microsoft.Win32.RegistryHive。LocalMachine作为第一个参数,您可以通过第二个参数(RegistryView)来区分是否使用64位或32位。Registry64和RegistryView.Registry32)。

Note that

请注意,

  • On a 64bit Windows, HKEY_LOCAL_MACHINE\Software\Wow6432Node contains values used by 32 bit applications running on the 64 bit system. Only true 64 bit applications store their values in HKEY_LOCAL_MACHINE\Software directly. The subtree Wow6432Node is entirely transparent for 32 bit applications, 32 bit applications still see HKEY_LOCAL_MACHINE\Software as they expect it (it is a kind of redirection). In older versions of Windows as well as 32 bit Windows 7 (and Vista 32 bit) the subtree Wow6432Node obviously does not exist.

    在64位Windows上,HKEY_LOCAL_MACHINE\Software\Wow6432Node包含32位运行在64位系统上的应用程序所使用的值。只有真正的64位应用程序可以直接在HKEY_LOCAL_MACHINE\软件中存储它们的值。子树Wow6432Node对于32位应用程序来说是完全透明的,32位应用程序仍然可以看到HKEY_LOCAL_MACHINE\软件(它是一种重定向)。在旧版本的Windows和32位Windows 7(和Vista 32位)中,子树Wow6432Node显然不存在。

  • Due to a bug in Windows 7 (64 bit), the 32 bit source code version always returns "Microsoft" regardless which organization you have registered while the 64 bit source code version returns the right organization.

    由于Windows 7(64位)中的一个错误,32位源代码版本总是返回“Microsoft”,不管您注册的是哪个组织,而64位源代码版本返回的是正确的组织。

Coming back to the example you've provided, do it the following way to access the 64 bit branch:

回到您提供的示例,使用以下方法访问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");

Update:

更新:

I'd like to add an interesting approach Johny Skovdal has suggested in the comments, which I've picked up to develop some useful functions by using his approach: In some situations you want to get back all keys regardless whether it is 32 bit or 64 bit. The SQL instance names are such an example. You can use a union query in that case as follows (C#6 or higher):

我想在评论中添加一个有趣的方法,我已经用他的方法开发了一些有用的函数:在某些情况下,无论它是32位还是64位,都需要返回所有的键。SQL实例名就是这样一个例子。在这种情况下,可以使用union查询(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);
}

Now you can simply use the functions above as follows:

现在您可以简单地使用上面的函数如下:

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}");
}

which will give you a list of the value names and values in sqlRegPath.

它将给出sqlRegPath中值名称和值的列表。

Note: You can access the default value of a key (displayed by the commandline tool REGEDT32.EXE as (Default)) if you omit the ValueName parameter in the corresponding functions above.

注意:您可以访问一个键的默认值(由命令行工具REGEDT32显示)。如果您在上面的相应函数中省略了ValueName参数,则EXE为(默认)。

Notice the null handling required in the functions because SQL server can be installed as 32 bit or as 64 bit. The functions are overloaded so you can still pass the 32 bit or 64 bit parameter if required - however, if you omit it then it will try to read 64 bit, if that fails (null value), it reads the 32 bit values.

注意在函数中需要的空处理,因为SQL server可以安装32位或64位。函数是重载的,因此如果需要,仍然可以传递32位或64位参数——但是,如果省略它,它将尝试读取64位,如果失败(空值),则读取32位值。

There is one speciality here: Because GetAllRegValueNames is usually used in a loop context (see example above), it returns an empty enumerable rather than null to simplify foreach loops: if it wouldn't be handled that way, the loop would have to be prefixed by an if statement checking for null which would be cumbersome having to do that - so that is dealt with once in the function.

这里有一个特色:因为GetAllRegValueNames通常是在一个循环中使用上下文(参见上面的例子),它将返回一个空可列举的而不是null来简化foreach循环:如果它不会这样处理,循环前缀必须由一个if语句检查null会麻烦不得不这么做——这是处理函数。

Why bothering about null? Because if you don't care, you'll have a lot more headaches finding out why that null reference exception was thrown in your code - you'd spend a lot of time finding out where and why it happened. And if it happened in production you'll be very busy studying log files or event logs (I hope you have logging implemented) ... better avoid null issues where you can in a defensive way. The operators ?., ?[...] and ?? can help you a lot (see the code provided above).

为什么困扰零呢?因为如果您不关心,您将会有更多的麻烦,找出为什么在您的代码中抛出了null引用异常—您将花费大量的时间找出它发生的原因和原因。如果它发生在生产中,您将非常忙碌地学习日志文件或事件日志(我希望您已经实现了日志记录)……最好避免用防守的方式解决问题。运营商吗?。?[…和? ?可以帮助您很多(参见上面提供的代码)。


Hint: You can use the free edition of Linqpad to test all examples under Windows. It doesn't require an installation. Don't forget to press F4 and enter Microsoft.Win32 in the Namespace import tab. In Visual Studio, you require using Microsoft.Win32; at the top of your code.

提示:您可以使用免费版的Linqpad来测试Windows下的所有示例。它不需要安装。别忘了按F4键进入微软。在名称空间导入选项卡中。在Visual Studio中,您需要使用Microsoft.Win32;在代码的顶部。

Tip: To familiarize yourself with the new null handling operators, try out (and debug) the following code in LinqPad:

提示:为了熟悉新的空处理操作符,请在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>"
}

If you're interested, here are some examples I put together showing what else you can do with the tool.

如果你感兴趣的话,这里有一些例子,我把它们放在一起,展示你可以用这个工具做些什么。

#3


4  

I don't have enough rep to comment, but it's worth pointing out that it works when opening a remote registry using OpenRemoteBaseKey. Adding the RegistryView.Registry64 parameter allows a 32-bit program on Machine A to access the 64-bit registry on Machine B. Before I passed that parameter, my program was reading the 32-bit after OpenRemoteBaseKey, and did not find the key I was after.

我没有足够的代表来评论,但值得指出的是,当使用OpenRemoteBaseKey打开远程注册表时,它是有效的。添加RegistryView。Registry64参数允许机器a上的32位程序在机器b*问64位注册表。在我传递这个参数之前,我的程序是在OpenRemoteBaseKey之后读取32位的,并且没有找到我要找的密钥。

Note: In my test, the remote machine was actually my machine, but I accessed it via OpenRemoteBaseKey, just as I would for a different machine.

注意:在我的测试中,远程机器实际上是我的机器,但是我通过OpenRemoteBaseKey访问它,就像我想换一台不同的机器一样。

#4


3  

If you cannot use .NET 4 with its RegistryKey.OpenBaseKey(..., RegistryView.Registry64), you need to use Windows API directly.

如果你不能使用。net 4的注册键。openbasekey(…,RegistryView.Registry64),您需要直接使用Windows API。

The minimal interop is like:

最小的互操作是:

internal enum RegistryFlags
{
    ...
    RegSz = 0x02,
    ...
    SubKeyWow6464Key = 0x00010000,
    ...
}

internal enum RegistryType
{
    RegNone = 0,
    ...
}

[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int RegGetValue(
    UIntPtr hkey, string lpSubKey, string lpValue, RegistryFlags dwFlags, 
    out RegistryType pdwType, IntPtr pvData, ref uint pcbData);

Use it like:

使用它:

IntPtr data = IntPtr.Zero;
RegistryType type;
uint len = 0;
RegistryFlags flags = RegistryFlags.RegSz | RegistryFlags.SubKeyWow6464Key;
UIntPtr key = (UIntPtr)((uint)RegistryHive.LocalMachine);

const string subkey= @"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL";
const string value = "SQLEXPRESS";

if (RegGetValue(key, subkey, value, flags, out type, data, ref len) == 0)
{
    data = Marshal.AllocHGlobal((int)len);
    if (RegGetValue(key, subkey, value, flags, out type, data, ref len) == 0)
    {
        string sqlExpressKeyName = Marshal.PtrToStringUni(data);
    }
}

#5


2  

try this (from a 32bit process):

试试这个(从一个32位的过程):

> %WINDIR%\sysnative\reg.exe query ...

(found that here).

(发现这里)。