如何从注册表中读取REG_二进制值,该注册表中安装了32位应用程序,但在64位操作系统上使用C#

如何从注册表中读取REG_二进制值,该注册表中安装了32位应用程序,但在64位操作系统上使用C#,c#,registry,C#,Registry,我想在Win7 64位计算机上使用C#获取注册表中此特定节点的值: 此值驻留在32位应用程序的安装存储其信息的注册表中。我面临的问题不是到达节点,而是返回一个有意义的值作为数组(string或int) 我使用的代码如下所示,并根据 及 我的清单如下: public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u); [DllImport("Advapi32.dll")] public static extern in

我想在Win7 64位计算机上使用C#获取注册表中此特定节点的值:

此值驻留在32位应用程序的安装存储其信息的注册表中。我面临的问题不是到达节点,而是返回一个有意义的值作为数组(string或int)

我使用的代码如下所示,并根据

我的清单如下:

public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u);

[DllImport("Advapi32.dll")]
public static extern int RegQueryValueEx(int hKey, string lpValueName, int lpReserved, ref uint lpType, byte[] lpData, ref uint lpcbData);

public enum RegSAM
{
    QueryValue = 0x0001,
    SetValue = 0x0002,
    CreateSubKey = 0x0004,
    EnumerateSubKeys = 0x0008,
    Notify = 0x0010,
    CreateLink = 0x0020,
    WOW64_32Key = 0x0200,
    WOW64_64Key = 0x0100,
    WOW64_Res = 0x0300,
    Read = 0x00020019,
    Write = 0x00020006,
    Execute = 0x00020019,
    AllAccess = 0x000f003f
}

string path = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion";

RegistryKey rkTest = Registry.LocalMachine.OpenSubKey(path);
try
{   
    int hkey = 0;
    uint lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, (int)RegSAM.QueryValue | (int)RegSAM.WOW64_32Key, out hkey);
    if (0 != lResult) hkey = 0;
    else
    {
        uint lpType = 0;
        uint lpcbData = 1024;
        byte[] Buffer = new Byte[1024];
        RegQueryValueEx(hkey, "DigitalProductID", 0, ref lpType, Buffer, ref lpcbData);
        ... at this point the buffer returns empty.
    }
}
catch (Exception exc) { };
但是当我执行它时,我的缓冲区是空的

如果我用StringBuilder类替换byte[],这里提供的代码可以到达顶部图像中显示的注册表的特定位置,并读取正常的字符串值,前提是注册表中的值是REG_SZ类型。但如果它是REG_二进制类型,我们能做什么

有人能告诉我怎么才能做到这一点吗

附言:

为了说明我已经研究了一个类似的问题好几天了,现在我已经使用下面的代码片段成功地将注册表中的REG_二进制值转换为可读的整数数组,但前提是该值位于WOW6432节点下

byte[] bytes = (byte[])rkTest.GetValue("DigitalProductID");
string s = Convert.ToBase64String(bytes);
List<int> int_array = new List<int>();
int temp_int = 0, i = 0;
for (i = 0; i < bytes.Length; i++) { temp_int = bytes[i]; int_array.Add(temp_int); }
byte[]bytes=(byte[])rkTest.GetValue(“DigitalProductID”);
字符串s=Convert.tobase64字符串(字节);
List int_数组=新列表();
int temp_int=0,i=0;
对于(i=0;i
这里我要解决的问题是注册表中32位应用程序以REG_二进制类型存储信息的区域


谢谢。

解决方案:

显然,我提供的第二个链接正是该页面上最后一个示例所需要的。要在代码中采用该解决方案,我只需添加GetRegKey64AsByteArray()方法,如下所示:

static public byte[] GetRegKey64AsByteArray(UIntPtr inHive, String inKeyName, RegSAM in32or64key, String inPropertyName)
{
    int hkey = 0;
    try {
        uint lResult = RegOpenKeyEx(inHive, inKeyName, 0, (int)RegSAM.QueryValue | (int)in32or64key, out hkey);
        if (0 != lResult) return null;
        RegistryValueKind lpType = 0;
        uint lpcbData = 2048;
        // Just make a big buffer the first time
        byte[] byteBuffer = new byte[1000];
        // The first time, get the real size
        RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, byteBuffer, ref lpcbData);
        // Now create a correctly sized buffer
        byteBuffer = new byte[lpcbData];
        // now get the real value
        RegQueryValueEx(hkey, inPropertyName, 0, ref lpType, byteBuffer, ref lpcbData);
        return byteBuffer;  
    }
    finally { if (0 != hkey) RegCloseKey(hkey); }
}
然后以字符串形式获取REG_二进制代码,如下所示:

byte[] byteValue64 = new byte[1024];
RegistryKey localKey = Registry.LocalMachine;
localKey = localKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");
if (localKey != null)
{
    byteValue64 = GetRegKey64AsByteArray(HKEY_LOCAL_MACHINE, @"SOFTWARE\Microsoft\Windows NT\CurrentVersion", RegSAM.WOW64_64Key, "DigitalProductID");
    string s = Convert.ToBase64String(byteValue64);
    //Need to do the following operation because array returns inverted!
    List<int> int_array = new List<int>();
    int temp_int = 0, i = 0;                
    for (i = 0; i < byteValue64.Length; i++) { temp_int = byteValue64[i]; int_array.Add(temp_int); }
    ... do something with the INT values here
}
byte[]byteValue64=新字节[1024];
RegistryKey localKey=Registry.LocalMachine;
localKey=localKey.OpenSubKey(@“SOFTWARE\Microsoft\Windows NT\CurrentVersion”);
if(localKey!=null)
{
byteValue64=GetRegKey64AsByteArray(HKEY_LOCAL_机器,@“SOFTWARE\Microsoft\Windows NT\CurrentVersion”,RegSAM.WOW64_64Key,“DigitalProductID”);
字符串s=Convert.tobase64字符串(字节值64);
//需要执行以下操作,因为数组返回反向!
List int_数组=新列表();
int temp_int=0,i=0;
对于(i=0;i
在最后一行,我将INT数组发送给一个函数,该函数给我一个可读的字母数字字符串


谢谢大家。

您已经把它倒过来了,您需要64位注册表视图。将EXE项目上的平台目标设置更改为AnyCPU(首选32位关闭)或使用RegistryKey.OpenBaseKey()选择视图。嗨,Hans,感谢您的努力,您提出了使用OpenBaseKey()的建议,第二个链接显示了我需要的解决方案。如果不是在这一页的底部,我可能会更快地得到它!这根本不像简单地放几行代码来实现我想要的那样简单。如果你已经找到了解决方案,你应该把它作为一个答案发布。不要把它放在问题中,然后添加一个“空白”答案链接回问题。那太乱了。如果你把它放在答案中,你就可以为将来有同样问题的访客接受答案。谢谢@mhlester我听从了你的建议。