如何在Windows XP中枚举/列出所有已安装的应用程序?

时间:2009-04-29 14:02:12

标签: c++ python winapi enumeration

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

我更喜欢用Python做,但C或C ++也没问题。

7 个答案:

答案 0 :(得分:11)

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

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall

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

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

答案 1 :(得分:10)

查看Win32_Product WMI(Windows Management Instrumentation)课程。 Here's a tutorial在Python中使用WMI。

答案 2 :(得分:8)

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

答案 3 :(得分:6)

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

答案 4 :(得分:4)

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

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

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

答案 5 :(得分:3)

用于在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"]);
        }

答案 6 :(得分:0)

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

对于它的价值,下面是我认为是迄今为止最完整的例子,虽然在C#中(我根据Framework 4.6.1编译它,但是较低版本也可以工作。)它列出了32 -bit和64位安装程序;它处理它使用的注册表项,并且它在不到一秒的时间内运行。至少在缓存开始之后。如果你可以提供改进,请建议它们而不仅仅是downvoting,我将更新代码。

仍然缺少的一件事是一些更新。例如,当我在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的回答。我怎么想念那个? LOL