32位程序在64位系统上读取注册表失败的问题解决

博客讲述了在Windows 10 x64环境下,32位程序无法直接读取64位注册表路径的问题。作者发现系统将32位程序的注册表路径重定向到了WOW6432Node,但尝试禁用重定向无效。解决方案包括:1) 使用64位程序直接读取;2) 创建32位和64位的独立exe,根据系统类型调用来读取。此外,还介绍了一种使用Win32API的简单方法,通过RegOpenKeyExA和特定标志读取注册表项。

1. 环境

  • Windows10 专业版 x64
  • Qt5.15.2 MSVC2019 32bit

2. 目的

读取卸载列表,如下:
在这里插入图片描述

3. 方法

使用QSettings读取注册表项:

SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall

枚举所有子项的DisplayName:
在这里插入图片描述

4. 现象和原因

确实获取到了一部分列表,但是我想要找的却没有,可是我直接在regedit工具里面看是有的。经过一番搜索,很快就找到了原因:

Note: On Windows, for 32-bit programs running in WOW64 mode, 
settings are stored in the following registry path: 
HKEY_LOCAL_MACHINE\Software\WOW6432node.

大意就是Windows会将32位程序的注册表路径重定向,MSDN有更具体的解释,有兴趣可自行按关键字wow64查找。
我去翻找注册表的这个路径:

SOFTWARE\\WOW6432node\\Microsoft\\Windows\\CurrentVersion\\Uninstall

果然找到了匹配的数据,但是我想要的数据并不在这里,怎么才能读取正确的路径?
又是一番搜索,绝大部分的回答都是说要用Wow64DisableWow64FsRedirection来禁用系统重定向,但尝试之后没有效果。

5. 有效的解决办法

5.1 使用64位程序

按msdn的文档描述,64位程序是没有重定向问题的,可以直接读取对应的注册表项,那将编译工具集换成64位即可解决问题。但是我们的程序因为业务需求,是需要跑在一部分32位系统上的,所以这里有个变通的方案:

1. 主程序还是用322. 读取注册表项的分别编译一个32位和64位的独立exe
3. 判断系统是32位的还是64位,然后调用对应的读取注册表程序,输出到文件
4. 主程序读取该文件

5.2 简单有效的方法

上面这个方法比较绕,后来侥幸搜到一篇博客,尝试之后有效,该方法不适用于QSettings,只能用win32 api来读取注册表。
这篇博客的主要思路是使用RegOpenKeyExA的系列api来读取注册项,然后通过KEY_WOW64_32KEY和KEY_WOW64_64KEY这两个值来控制读取位置,具体请参考:

https://www.xuebuyuan.com/1567776.html

最终的代码如下:

#include <windows.h>

#include <iostream>

using namespace std;

int main() {
    HKEY key;
    string rootKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
    if (ERROR_SUCCESS != RegOpenKeyExA(HKEY_LOCAL_MACHINE, rootKey.c_str(), NULL, KEY_WOW64_64KEY | KEY_READ, &key)) {
        return 1;
    }

    const int MAX_LEN = 256 * sizeof(char);
    DWORD keyCount = MAX_LEN;
    if (ERROR_SUCCESS != RegQueryInfoKey(key, NULL, NULL, NULL, &keyCount, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) {
        return 0;
    }

    char buf[MAX_LEN] = {0};
    for (int i = 0; i < (int)keyCount; i++) {
        DWORD keySize = MAX_LEN;
        RegEnumKeyExA(key, i, buf, &keySize, NULL, NULL, NULL, NULL);

        DWORD dwType;
        HKEY subKey;
        if (ERROR_SUCCESS == RegOpenKeyExA(key, buf, NULL, KEY_READ, &subKey)) {
            char val[MAX_LEN] = {0};
            keySize = MAX_LEN;
            RegQueryValueExA(subKey, "DisplayName", 0, &dwType, (LPBYTE)val, &keySize);
            cout << val << endl;
            RegCloseKey(subKey);
        }
    }

    RegCloseKey(key);

    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值