当前位置: 首页 > news >正文

RegEnumKeyExW函数遍历注册表的错乱问题

程序测试环境是:windows 10 64位系统,c++程序。

#include <windows.h>
#include <iostream>
#include <vector>
#include <string>// 辅助函数:从指定的注册表路径中获取已安装的软件列表
std::vector<std::wstring> GetInstalledSoftwareFromKey(HKEY rootKey, const std::wstring& subKey) {std::vector<std::wstring> installedSoftware;HKEY hKey;// 打开注册表项if (RegOpenKeyExW(rootKey, subKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS) {return installedSoftware;}FILETIME ftLastWriteTime;wchar_t szSubKeyName[MAX_PATH] = L"";DWORD cchSubKeyName = MAX_PATH;DWORD dwIndex = 0;// 遍历注册表项while (RegEnumKeyExW(hKey, dwIndex++, szSubKeyName, &cchSubKeyName, NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS) {HKEY hSubKey;std::wstring subSubKey = subKey + L"\\" + szSubKeyName;// 打开子项if (RegOpenKeyExW(rootKey, subSubKey.c_str(), 0, KEY_READ, &hSubKey) == ERROR_SUCCESS) {DWORD type = 0;DWORD size = MAX_PATH;wchar_t displayName[MAX_PATH] = L"";DWORD displayVersion[MAX_PATH] = 0;// 获取显示名称if (RegQueryValueExW(hSubKey, L"DisplayName", NULL, &type, (LPBYTE)displayName, &size) == ERROR_SUCCESS) {installedSoftware.push_back(std::wstring(displayName));}RegCloseKey(hSubKey);}cchSubKeyName = MAX_PATH;}RegCloseKey(hKey);return installedSoftware;
}// 主函数:获取所有已安装的软件
std::vector<std::wstring> GetAllInstalledSoftware() {std::vector<std::wstring> allInstalledSoftware;// 定义需要检查的注册表路径const std::wstring paths[] = {L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",L"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall",L"SOFTWARE\\Kingsoft"};// 检查HKEY_LOCAL_MACHINEfor (const auto& path : paths) {auto softwareList = GetInstalledSoftwareFromKey(HKEY_LOCAL_MACHINE, path);allInstalledSoftware.insert(allInstalledSoftware.end(), softwareList.begin(), softwareList.end());}// 检查HKEY_CURRENT_USERfor (const auto& path : paths) {auto softwareList = GetInstalledSoftwareFromKey(HKEY_CURRENT_USER, path);allInstalledSoftware.insert(allInstalledSoftware.end(), softwareList.begin(), softwareList.end());}return allInstalledSoftware;
}int main() {std::vector<std::wstring> installedSoftware = GetAllInstalledSoftware();std::wcout << L"已安装的软件列表:\n";for (const auto& software : installedSoftware) {std::wcout << software << L"\n";}return 0;
}

以上就是一个完整遍历注册表的代码。我在vscode自己写的demo测试发现可以遍历到office软件,比如word、excel等。

但是当我把这部分代码移植到我的工程里之后,发现就无法遍历到office软件了。而且还发现另一个现象:

RegEnumKeyExW函数在HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall下遍历时,竟然遍历到HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall下的信息

最终定位到原因是,我的工程程序是32位的,在64位Windows系统中,32位应用程序默认访问的是32位注册表视图,这会导致一些路径被重定向。

修改代码如下:

#include <windows.h>
#include <iostream>
#include <vector>
#include <string>// 辅助函数:从指定的注册表路径中获取已安装的软件列表
std::vector<std::wstring> GetInstalledSoftwareFromKey(HKEY rootKey, const std::wstring& subKey, REGSAM samDesired) {std::vector<std::wstring> installedSoftware;HKEY hKey;// 打开注册表项if (RegOpenKeyExW(rootKey, subKey.c_str(), 0, samDesired, &hKey) != ERROR_SUCCESS) {return installedSoftware;}FILETIME ftLastWriteTime;wchar_t szSubKeyName[MAX_PATH] = L"";DWORD cchSubKeyName = MAX_PATH;DWORD dwIndex = 0;// 遍历注册表项while (RegEnumKeyExW(hKey, dwIndex++, szSubKeyName, &cchSubKeyName, NULL, NULL, NULL, &ftLastWriteTime) == ERROR_SUCCESS) {HKEY hSubKey;std::wstring subSubKey = subKey + L"\\" + szSubKeyName;// 打开子项if (RegOpenKeyExW(rootKey, subSubKey.c_str(), 0, samDesired, &hSubKey) == ERROR_SUCCESS) {DWORD type = 0;DWORD size = MAX_PATH;wchar_t displayName[MAX_PATH] = L"";DWORD displayVersion[MAX_PATH] = 0;// 获取显示名称if (RegQueryValueExW(hSubKey, L"DisplayName", NULL, &type, (LPBYTE)displayName, &size) == ERROR_SUCCESS) {installedSoftware.push_back(std::wstring(displayName));}RegCloseKey(hSubKey);}cchSubKeyName = MAX_PATH;}RegCloseKey(hKey);return installedSoftware;
}// 主函数:获取所有已安装的软件
std::vector<std::wstring> GetAllInstalledSoftware() {std::vector<std::wstring> allInstalledSoftware;// 定义需要检查的注册表路径const std::wstring paths[] = {L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",L"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall",L"SOFTWARE\\Kingsoft"};// 检查HKEY_LOCAL_MACHINEfor (const auto& path : paths) {auto softwareList = GetInstalledSoftwareFromKey(HKEY_LOCAL_MACHINE, path, KEY_READ | KEY_WOW64_64KEY);allInstalledSoftware.insert(allInstalledSoftware.end(), softwareList.begin(), softwareList.end());// 32位视图softwareList = GetInstalledSoftwareFromKey(HKEY_LOCAL_MACHINE, path, KEY_READ | KEY_WOW64_32KEY);allInstalledSoftware.insert(allInstalledSoftware.end(), softwareList.begin(), softwareList.end());}// 检查HKEY_CURRENT_USERfor (const auto& path : paths) {auto softwareList = GetInstalledSoftwareFromKey(HKEY_CURRENT_USER, path, KEY_READ);allInstalledSoftware.insert(allInstalledSoftware.end(), softwareList.begin(), softwareList.end());}return allInstalledSoftware;
}int main() {std::vector<std::wstring> installedSoftware = GetAllInstalledSoftware();std::wcout << L"已安装的软件列表:\n";for (const auto& software : installedSoftware) {std::wcout << software << L"\n";}return 0;
}

重点看 RegOpenKeyExW函数的参数samDesired的值。


http://www.mrgr.cn/news/74904.html

相关文章:

  • 常见混淆概念理清:从搜索引擎和检索引擎的区别说起
  • Linux中.NET读取excel组件,不会出现The type initializer for ‘Gdip‘ threw an exception异常
  • 【Hadoop实训】Hive 数据操作②
  • 万字长文解读深度学习——ViT、ViLT、DiT
  • CSS多列布局:打破传统布局的束缚
  • 常见git命令记录
  • 修改电脑ip
  • Java线程的sleep和wait的区别
  • 5 for循环——抽奖概率计算器
  • Puppeteer教程:使用CSS选择器点击和爬取动态数据
  • Apache Paimon、Apache Hudi、Apache Iceberg对比分析
  • 最懂AI算法的软件,MATLAB实战深度学习大模型带给我不少惊喜!
  • JacksonObjectMapper的作用
  • 【深度学习】神经网络优化方法 正则化方法 价格分类案例
  • Android Studio 中三方库依赖无法找到的解决方案
  • 后台管理系统的通用权限解决方案(十五)基于注解和切面实现操作日志记录
  • 【Linux】 shell 学习汇总[转载]
  • Spark读MySQL数据rdd分区数受什么影响,读parquet、hdfs、hive、Doris、Kafka呢?
  • 接口自动化环境搭建
  • 连接数据库导出数据库信息支持excel pdf html markdown
  • 03 P1314 [NOIP2011 提高组] 聪明的质监员
  • 群控系统服务端开发模式-应用开发-前端角色功能开发
  • AI界盛会来袭!高录用EI会议(IS-AII 2025)你绝不能错过!
  • 【B+树特点】
  • Aippyy如何写论文?ai人工智能写作哪家好?
  • java项目-jenkins任务的创建和执行