Pergunta

Quando eu digo "aplicativo instalado", eu basicamente significa qualquer aplicação visível no [Painel de Controle] -> [Adicionar / Remover Programas].

Eu preferiria fazê-lo em Python, mas C ou C ++ também é bom.

Foi útil?

Solução

Se você quer dizer a lista de aplicativos instalados que é mostrado em Adicionar \ remover programas no painel de controle, você pode encontrá-lo na chave de registo:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall

mais informações sobre como a árvore de registro é estruturado pode ser encontrada aqui .

Você precisa usar o winreg API em python para ler os valores de o registro.

Outras dicas

Confira o Win32_Product WMI (Windows Management Instrumentation) classe. Aqui está um tutorial sobre o uso WMI em Python.

Painel de Controle utiliza Win32 COM API, que é o método oficial (ver Google Groups, Win32)
Nunca confie em registro.

The Script Repository Microsoft tem um script para listar todos os softwares instalados.

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

A melhor implementação baseada em registro que eu tenho visto é aquele escrito por Chris Wright (chris128) publicadas em http://www.vbforums.com/showthread.php?t=598355 . Ele usa várias chaves de registro e é muito mais complexa do que qualquer uma das respostas actualmente publicados aqui. Ele parece produzir resultados idênticos para o Adicionar / Remover aplicativo programas e, como o aplicativo ARP também fornece uma opção para incluir atualizações.

Embora seja implementado em VB.NET, ele deve ser fácil para converter a outras linguagens .NET como C # ou IronPython. Imagino que a conversão para IronPython primeiro deve torná-lo bastante fácil para a porta para Python regular, se é isso que você quer, mas eu só converteu-o para C # mesmo e, em seguida, limpar o código um pouco.

Apenas um pequeno bug em apontar: não GetUserInstallerKeyPrograms () não adicionar a versão para programas do usuário à lista, mesmo que ele extrai-lo. Isso é fácil de correção embora.

C # .NET código para obter a lista de software instalado usando WMI no XP e Win7 (WMI é a única maneira em win7)

    WqlObjectQuery wqlQuery =
      new WqlObjectQuery("SELECT * FROM Win32_Product");
        ManagementObjectSearcher searcher =
            new ManagementObjectSearcher(wqlQuery);

        foreach (ManagementObject software in searcher.Get()) {
            Console.WriteLine(software["Caption"]);
        }

Eu sei que esta questão é velho, o OP mencionado XP e também mencionou Python, C ou C ++, mas eu achei que um monte de informações na rede sobre este tema está incompleto ou incorreto. Um exemplo do último é a sugestão de se usar o WMI - especificamente, a classe Win32_Product; no entanto, como é observado em outros lugares, esse método é lento , em parte porque, acredite ou não, cada MSI encontrado na verdade é executado a sua reparação. Eu chamo isso de solução incorreta por causa de como dolorosamente lento que é e por causa de seu efeito colateral desagradável. Por exemplo, você já optou por desativar o serviço Windows de um programa, mas select * from Win32_Product chamando, como parte da garantia de que o MSI reparação corridas, aparentemente vai reativar o serviço.

Por que vale a pena, a seguir é o que eu considero ser o exemplo mais completo até à data, ainda que em C # (I compilado contra Framework 4.6.1 mas as versões mais baixas podem funcionar também.) Ele lista 32-bit e 64 bit programas instalados; que dispõe chaves do registro que ele usa e ele é executado em menos de um segundo, pelo menos depois cache chutes. Se você pode oferecer melhorias, por favor, sugerem-los em vez de apenas downvoting, e eu vou atualizar o código.

Uma coisa que é ainda está faltando é algumas atualizações. Por exemplo, quando eu executá-lo no meu sistema Windows 10 e compará-lo com o Painel de Controle | Programas e Recursos | Atualizações instaladas, noto que ele não mostra Security Update for Adobe Flash Player por algum motivo.

Eu não tenho nenhuma boa razão para o método anônimo, é apenas como eu estava pensando no momento -. Uma espécie de solução método-dentro-do-método

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;
    }
}

[Suspiro] e então viu I @ resposta de PolyTekPatrick. Como eu perdi isso? LOL

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top