程序测试环境是: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_MACHINE
for (const auto& path : paths) {
auto softwareList = GetInstalledSoftwareFromKey(HKEY_LOCAL_MACHINE, path);
allInstalledSoftware.insert(allInstalledSoftware.end(), softwareList.begin(), softwareList.end());
}
// 检查HKEY_CURRENT_USER
for (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_MACHINE
for (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_USER
for (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的值。