WTLATLVisual C++ 7.1Visual C++ 8.0Visual Studio 6Visual C++ 7.0Visual Studio .NET 2003Windows 2003Windows 2000Visual C++ 6.0Windows XPMFCIntermediateDevVisual StudioWindowsC++
如何获取已安装应用程序列表






4.66/5 (23投票s)
2004年4月21日
1分钟阅读

216147

8932
复制在“添加/删除程序”控制面板小程序中看到的列表。
引言
最近,我在 Visual C++ 论坛 中回答了一个问题,关于如何复制在“控制面板”中选择“添加/删除程序”时看到的已安装程序的列表,我认为这个解决方案可以写成一篇不错的(如果很基础)文章。
要获取列表非常简单 - 首先您需要打开以下注册表项
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
然后只需枚举所有条目并从每个条目中获取 DisplayName 值。
MFC/WTL/ATL
为了迎合所有人的口味,我包含了以下环境的代码版本
- MFC
- WTL
- ATL7(包含在 Visual Studio 2002/2003 中)
MFC 和 WTL 版本之间的区别很微妙 - MFC 版本将程序列表存储在 CStringArray
中,而 WTL 版本使用 CSimpleArray<CString>
。
ATL7 版本使用了方便的 CRegKey
类。
使用 CInstalledSoftware 类
要使用此类,只需在您的应用程序中声明 CInstalledSoftware
类的一个实例,构造函数会将已安装程序的列表填充到公共 m_aPrograms
成员中。 例如,要填充一个 MFC 列表框,您可以使用这样的代码
CInstalledSoftware apps; for (int i = 0; i < apps.m_aPrograms.GetCount(); i++) m_wndList.AddString(apps.m_aPrograms[i]);
就是这样! 这不是火箭科学!
构建列表 - MFC/WTL
MFC/WTL 版本的代码使用 Win32 注册表调用来构建列表
void BuildList(void) { HKEY hKey; if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, IS_KEY, 0, KEY_READ, &hKey) != ERROR_SUCCESS) return; DWORD dwIndex = 0; LONG lRet; DWORD cbName = IS_KEY_LEN; TCHAR szSubKeyName[IS_KEY_LEN]; while ((lRet = ::RegEnumKeyEx(hKey, dwIndex, szSubKeyName, &cbName, NULL, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS) { // Do we have a key to open? if (lRet == ERROR_SUCCESS) { // Open the key and get the value HKEY hItem; if (::RegOpenKeyEx(hKey, szSubKeyName, 0, KEY_READ, &hItem) != ERROR_SUCCESS) continue; // Opened - look for "DisplayName" TCHAR szDisplayName[IS_KEY_LEN]; DWORD dwSize = sizeof(szDisplayName); DWORD dwType; if (::RegQueryValueEx(hItem, IS_DISPLAY, NULL, &dwType, (LPBYTE)&szDisplayName, &dwSize) == ERROR_SUCCESS) { // Add to the main array m_aPrograms.Add(szDisplayName); } ::RegCloseKey(hItem); } dwIndex++; cbName = IS_KEY_LEN; } ::RegCloseKey(hKey); }
ATL7 版本使用更易读的 CRegKey
类
void BuildList(void) { CRegKey reg; if (reg.Open(HKEY_LOCAL_MACHINE, IS_KEY, KEY_READ) != ERROR_SUCCESS) return; DWORD dwIndex = 0; DWORD cbName = IS_KEY_LEN; TCHAR szSubKeyName[IS_KEY_LEN]; LONG lRet; while ((lRet = reg.EnumKey(dwIndex, szSubKeyName, &cbName)) != ERROR_NO_MORE_ITEMS) { if (lRet == ERROR_SUCCESS) { CRegKey regItem; if (regItem.Open(reg, szSubKeyName, KEY_READ) == ERROR_SUCCESS) { // Get the "DisplayName" value ULONG ulChars; if (regItem.QueryStringValue(IS_DISPLAY, NULL, &ulChars) == ERROR_SUCCESS) { CString strName; regItem.QueryStringValue(IS_DISPLAY, strName.GetBuffer(ulChars), &ulChars); strName.ReleaseBuffer(); // Add to the array m_aPrograms.Add(strName); } } } dwIndex++; cbName = IS_KEY_LEN; } }
好的,此类不会赢得任何奖项,但希望其他人会觉得它有用。 欢迎评论!