65.9K
CodeProject 正在变化。 阅读更多。
Home

如何获取已安装应用程序列表

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.66/5 (23投票s)

2004年4月21日

1分钟阅读

viewsIcon

216147

downloadIcon

8932

复制在“添加/删除程序”控制面板小程序中看到的列表。

Sample screenshot

引言

最近,我在 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;
 }
}

好的,此类不会赢得任何奖项,但希望其他人会觉得它有用。 欢迎评论!

© . All rights reserved.