【问题标题】:How can I enumerate/list all installed applications in Windows XP?如何枚举/列出 Windows XP 中所有已安装的应用程序?
【发布时间】:2010-10-22 14:19:13
【问题描述】:

当我说“已安装的应用程序”时,我基本上是指在[控制面板]->[添加/删除程序]中可见的任何应用程序。

我更喜欢用 Python 来做,但 C 或 C++ 也可以。

【问题讨论】:

  • 您如何定义“已安装的应用程序”?

标签: c++ python winapi enumeration


【解决方案1】:

如果您指的是控制面板中添加\删除程序中显示的已安装应用程序列表,您可以在注册表项中找到它:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall

more info about how the registry tree is structured can be found here.

您需要在 python 中使用winreg API 从注册表中读取值。

【讨论】:

  • 我的系统上的那个键是空的。检查链接底部的操作系统,您会发现它不适用于 WinXP。
  • @R.A,这个注册表项包含很多子项(子文件夹)。每个代表卸载列表中的一个程序。请在上述链接中阅读该键的结构。
  • 是的,很抱歉,我实际上在那个 regkey 中找到了它们,我的系统冻结了一段时间,我做出了快速判断,因为你提供的链接没有提到 XP。猜猜这篇文章只是旧的。
  • XP和Vista都可以使用:vistax64.com/attachments/tutorials/…
  • 该知识库文章列出了旧版本的操作系统。它可能会或可能不会在较新的版本中工作。除非您可以在 MSDN 库中找到它的文档,否则您可能不应该依赖它。我会按照其他答案的建议查看 WMI。
【解决方案2】:

查看Win32_Product WMI(Windows 管理规范)类。 Here's a tutorial 在 Python 中使用 WMI。

【讨论】:

  • 我支持这个。习惯 WMI 将帮助您完成其他与 Windows 管理员相关的任务。我最近写了一个关于如何在 C++ 中使用 WMI 的示例。 blog.emptycrate.com/node/376
  • 不过有一些注意事项。可以在某些 PC 上禁用 WMI。此外,它并未列出控制面板小程序中可见的所有应用程序——仅列出由兼容安装程序安装的应用程序。
【解决方案3】:

控制面板使用 Win32 COM api,这是官方的方法(参见 Google Groups,Win32)
永远不要依赖注册表。

【讨论】:

  • 晚了很多年,但 -1 表示没有说明使用了 哪个 COM API。一个usenet组很大;在答案中说“去谷歌吧”是不够的。
  • 控制面板使用 COM API,但我猜 API 然后从注册表中读取。这间接意味着它依赖于注册表。
【解决方案4】:

Microsoft Script Repository 有一个用于列出所有已安装软件的脚本。

import win32com.client
strComputer = "."
objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator")
objSWbemServices = objWMIService.ConnectServer(strComputer,"root\cimv2")
colItems = objSWbemServices.ExecQuery("Select * from Win32_Product")
for objItem in colItems:
    print "Caption: ", objItem.Caption
    print "Description: ", objItem.Description
    print "Identifying Number: ", objItem.IdentifyingNumber
    print "Install Date: ", objItem.InstallDate
    print "Install Date 2: ", objItem.InstallDate2
    print "Install Location: ", objItem.InstallLocation
    print "Install State: ", objItem.InstallState
    print "Name: ", objItem.Name
    print "Package Cache: ", objItem.PackageCache
    print "SKU Number: ", objItem.SKUNumber
    print "Vendor: ", objItem.Vendor
    print "Version: ", objItem.Version

【讨论】:

    【解决方案5】:

    我见过的最好的基于注册表的实现是由 Chris Wright (chris128) 编写的,发布在http://www.vbforums.com/showthread.php?t=598355。它使用多个注册表项,并且比当前在此处发布的任何答案都复杂得多。它似乎产生了与添加/删除程序应用程序相同的结果,并且与 ARP 应用程序一样,它也提供了包含更新的选项。

    虽然它是在 VB.NET 中实现的,但它应该很容易转换为其他 .NET 语言,如 C# 或 IronPython。我想如果你想要的话,首先转换到 IronPython 应该可以很容易地移植到常规 Python,但我只是自己将它转换为 C#,然后稍微清理一下代码。

    只需要指出一个小错误:GetUserInstallerKeyPrograms() 不会将用户程序的版本添加到列表中,即使它提取了它。不过这很容易解决。

    【讨论】:

    • 谢谢,这个最有用了。
    【解决方案6】:

    xp和win7中使用wmi获取已安装软件列表的c#.net代码(wmi是win7中唯一的方法)

        WqlObjectQuery wqlQuery =
          new WqlObjectQuery("SELECT * FROM Win32_Product");
            ManagementObjectSearcher searcher =
                new ManagementObjectSearcher(wqlQuery);
    
            foreach (ManagementObject software in searcher.Get()) {
                Console.WriteLine(software["Caption"]);
            }
    

    【讨论】:

      【解决方案7】:

      OP提到了XP,也提到了Python、C或C++,但我发现网上很多关于这个话题的信息要么不完整,要么不正确。后者的一个例子是使用 WMI 的建议——特别是 Win32_Product 类;然而,正如其他地方所指出的那样,该方法缓慢,部分原因是,不管你信不信,发现的每个 MSI 都会实际运行其修复。我称该解决方案不正确,因为它的速度非常缓慢,并且具有令人讨厌的副作用。例如,您已经选择禁用某个程序的 Windows 服务,但调用 select * from Win32_Product,作为确保 MSI 修复运行的一部分,显然会重新启用该服务。

      对于它的价值,下面是我认为是迄今为止最完整的示例,尽管是在 C# 中(我根据 Framework 4.6.1 编译它,但较低版本也可以工作。)它列出了 32 位和 64 -位安装程序;它会处理它使用的注册表项,并在一秒钟内运行,至少在缓存启动之后。欢迎改进。

      仍然缺少的一件事是一些更新。例如,当我在 Windows 10 系统上运行它并将其与控制面板 | 进行比较时程序和功能 |已安装更新,我注意到由于某种原因它没有显示Security Update for Adobe Flash Player

      我对匿名方法没有任何充分的理由,这正是我当时的想法——一种方法中的方法解决方案。

      using System;
      using System.Collections.Generic;
      using System.Runtime.InteropServices;
      using System.Text;
      using System.Text.RegularExpressions;
      using Microsoft.Win32;
      
      class Program
      {
          static void Main(string[] args)
          {
              var result = InstalledProgram.GetAllInstalledPrograms();
      
              result.Sort((a, b) => a.DisplayName.CompareTo(b.DisplayName));
      
              foreach(var program in result)
              {
                  if(!program.IsSystemComponent && !program.IsKB) Console.WriteLine(program.Dump());
              }
          }
      }
      
      public enum PlatformTypes
      {
          x86,
          amd64
      }
      
      public class InstalledProgram
      {
          [DllImport("advapi32.dll")]
          extern public static int RegQueryInfoKey(
              Microsoft.Win32.SafeHandles.SafeRegistryHandle hkey,
              StringBuilder lpClass,
              ref uint lpcbClass,
              IntPtr lpReserved,
              IntPtr lpcSubKeys,
              IntPtr lpcbMaxSubKeyLen,
              IntPtr lpcbMaxClassLen,
              IntPtr lpcValues,
              IntPtr lpcbMaxValueNameLen,
              IntPtr lpcbMaxValueLen,
              IntPtr lpcbSecurityDescriptor,
              out long lpftLastWriteTime
          );
      
          public string DisplayName { get; private set; }
          public string UninstallString { get; private set; }
          public string KBNumber { get; private set; }
          public string DisplayIcon { get; private set; }
          public string Version { get; private set; }
          public DateTime InstallDate { get; private set; }
          public PlatformTypes Platform { get; private set; }
          public bool IsSystemComponent { get; private set; }
          public bool IsKB { get { return !string.IsNullOrWhiteSpace(KBNumber); } }
      
          public static List<InstalledProgram> GetAllInstalledPrograms()
          {
              var result = new List<InstalledProgram>();
      
              Action<PlatformTypes, RegistryKey, string> getRegKeysForRegPath = (platform, regBase, path) =>
              {
                  using(var baseKey = regBase.OpenSubKey(path))
                  {
                      if(baseKey != null)
                      {
                          string[] subKeyNames = baseKey.GetSubKeyNames();
                          foreach(string subkeyName in subKeyNames)
                          {
                              using(var subKey = baseKey.OpenSubKey(subkeyName))
                              {
                                  object o;
      
                                  o = subKey.GetValue("DisplayName");
                                  string displayName = o != null ? o.ToString() : "";
                                  o = subKey.GetValue("UninstallString");
                                  string uninstallString = o != null ? o.ToString() : "";
                                  o = subKey.GetValue("KBNumber");
                                  string kbNumber = o != null ? o.ToString() : "";
                                  o = subKey.GetValue("DisplayIcon");
                                  string displayIcon = o != null ? o.ToString() : "";
                                  o = subKey.GetValue("DisplayVersion");
                                  string version = o != null ? o.ToString() : "";
                                  o = subKey.GetValue("InstallDate");
                                  DateTime installDate = o != null ? parseInstallDate(o.ToString()) : default(DateTime);
                                  o = subKey.GetValue("SystemComponent");
                                  bool isSystemComponent = o != null ? o.ToString() == "1" : false;
      
                                  // Sometimes, you need to get the KB number another way.
                                  if(kbNumber == "")
                                  {
                                      var match = Regex.Match(displayName, @".*?\((KB\d+?)\).*");
                                      if(match.Success) kbNumber = match.Groups[1].ToString();
                                  }
      
                                  // Sometimes, the only way you can get install date is from the last write
                                  // time on the registry key.
                                  if(installDate == default(DateTime))
                                  {
                                      string keyFull = baseKey + "\\" + subkeyName + "\\DisplayVersion";
                                      var sb = new StringBuilder(64);
                                      uint sbLen = 65;
      
                                      RegQueryInfoKey(
                                              subKey.Handle
                                              , sb
                                              , ref sbLen
                                              , IntPtr.Zero
                                              , IntPtr.Zero
                                              , IntPtr.Zero
                                              , IntPtr.Zero
                                              , IntPtr.Zero
                                              , IntPtr.Zero
                                              , IntPtr.Zero
                                              , IntPtr.Zero
                                              , out long lastWriteTime);
      
                                      installDate = DateTime.FromFileTime(lastWriteTime);
                                  }
      
                                  if(displayName != "" && uninstallString != "")
                                  {
                                      result.Add(new InstalledProgram
                                      {
                                          DisplayName = displayName,
                                          UninstallString = uninstallString,
                                          KBNumber = kbNumber,
                                          DisplayIcon = displayIcon,
                                          Version = version,
                                          InstallDate = installDate,
                                          Platform = platform,
                                          IsSystemComponent = isSystemComponent
                                      });
                                  }
                              }
                          }
                      }
                  }
              };
      
              getRegKeysForRegPath(PlatformTypes.amd64, Registry.LocalMachine, @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
              getRegKeysForRegPath(PlatformTypes.amd64, Registry.CurrentUser, @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
              if(Environment.Is64BitOperatingSystem)
              {
                  getRegKeysForRegPath(PlatformTypes.x86, Registry.LocalMachine, @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall");
                  getRegKeysForRegPath(PlatformTypes.x86, Registry.CurrentUser, @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall");
              }
      
              return result;
          }
      
          public string Dump()
          {
              return Platform + "\t" + DisplayName + "\t" + InstallDate + "\t" + DisplayIcon + "\t" + Version + "\t" + KBNumber + "\t" + UninstallString;
          }
      
          private static DateTime parseInstallDate(string installDateStr)
          {
              DateTime.TryParseExact(
                      installDateStr
                      , format: "yyyyMMdd"
                      , provider: new System.Globalization.CultureInfo("en-US")
                      , style: System.Globalization.DateTimeStyles.None
                      , result: out DateTime result);
      
              return result;
          }
      
          public override string ToString()
          {
              return DisplayName;
          }
      }
      

      [叹气] 然后我看到了@PolyTekPatrick 的回答。我怎么错过了?

      【讨论】:

        猜你喜欢
        • 2013-02-16
        • 1970-01-01
        • 1970-01-01
        • 2023-01-07
        • 2012-08-27
        • 2012-07-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多