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

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;
}
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 VB6 中,在调试模式下能够正常访问注册表数据,但在安装后无法成功访问的问题可能有以下几个原因: 1. 权限问题:在调试模式下,你可能以管理员权限运行 VB6 IDE,因此可以访问和修改注册表。但是在正常安装后,应用程序将以普通用户权限运行,这可能导致无法访问某些注册表项。确保你的应用程序具有足够的权限来读取所需的注册表项。 2. 注册表路径错误:在调试模式下,你可能使用了一个特定的注册表路径,但是在正常安装后,这个路径可能不再有效。确保你在代码中使用的注册表路径是正确的,并且与实际安装后生成的注册表路径相匹配。 3. 操作系统位数不匹配:如果你的应用程序是 32 位的,但是在 64 位的操作系统上运行,可能会导致访问注册表失败。在 64 位操作系统上,32 位应用程序需要访问的注册表项位于 "Wow6432Node" 子项下。请确保你的代码正确处理了操作系统位数不匹配的情况。 4. 缺少依赖项:如果你的应用程序依赖于某些组件或库来访问注册表数据,确保这些依赖项已正确安装并配置。 解决问题的方法可能因具体情况而异,但通常的解决步骤包括: 1. 确保应用程序具有足够的权限来读取注册表。 2. 检查注册表路径是否正确,并与实际安装后生成的路径相匹配。 3. 如果在 64 位操作系统上运行 32 位应用程序,确保代码正确处理了注册表路径的位数不匹配情况。 4. 检查并确保所有必需的依赖项已正确安装和配置。 如果问题仍然存在,你可能需要进一步调查该应用程序和相关环境的文档或寻求相关技术支持。 请注意,以上回答是基于一般情况的推测,具体情况可能有所不同。如有需要,请提供更多的上下文和详细信息以便更准确地解决问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值