9

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

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

4

7 回答 7

12

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

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall

可以在此处找到有关注册表树结构的更多信息

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

于 2009-04-29T14:06:25.900 回答
10

查看Win32_Product WMI(Windows 管理规范)类。这是在 Python 中使用 WMI 的教程

于 2009-04-29T14:05:59.643 回答
8

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

于 2009-04-29T15:57:31.497 回答
7

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
于 2009-04-29T22:23:37.730 回答
6

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

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

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

于 2012-03-18T08:30:37.160 回答
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"]);
        }
于 2010-08-18T11:43:00.353 回答
0

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 的回答。我怎么错过了?

于 2018-05-15T07:39:01.643 回答