Domanda

Quando dico "applicazione installata", intendo sostanzialmente qualsiasi applicazione visibile in [Pannello di controllo] - > [Aggiungi / Rimuovi programmi].

Preferirei farlo in Python, ma anche C o C ++ va bene.

È stato utile?

Soluzione

Se si intende l'elenco delle applicazioni installate visualizzato in Installazione applicazioni nel pannello di controllo, è possibile trovarlo nella chiave del Registro di sistema:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall

maggiori informazioni su come è strutturata la struttura del registro qui .

Devi usare API winreg in Python per leggere i valori da il registro.

Altri suggerimenti

Dai un'occhiata al Win32_Product WMI (Windows Classe di strumentazione di gestione). Ecco un tutorial sull'uso di WMI in Python.

Il pannello di controllo utilizza API COM Win32, che è il metodo ufficiale (vedi Google Gruppi, Win32)
Non fare mai affidamento sul registro.

Il Microsoft Script Repository ha uno script per elencare tutto il software installato.

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

La migliore implementazione basata su registro che ho visto è quella scritta da Chris Wright (chris128) pubblicata su http://www.vbforums.com/showthread.php?t=598355 . Utilizza più chiavi di registro ed è molto più complesso di qualsiasi delle risposte attualmente pubblicate qui. Sembra produrre risultati identici all'app Aggiungi / Rimuovi Programmi e, come l'app ARP, offre anche un'opzione per includere gli aggiornamenti.

Sebbene sia implementato in VB.NET, dovrebbe essere facile da convertire in altri linguaggi .NET come C # o IronPython. Immagino che la conversione in IronPython prima dovrebbe rendere abbastanza facile il porting su Python normale se è quello che vuoi, ma l'ho convertito in C # solo io e poi ho ripulito un po 'il codice.

Solo un piccolo bug da sottolineare: GetUserInstallerKeyPrograms () non aggiunge la versione per i programmi utente all'elenco, anche se lo estrae. Questo è facile da risolvere però.

Codice C # .net per ottenere l'elenco dei software installati utilizzando WMI in xp e win7 (wmi è l'unico modo in win7)

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

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

So che questa domanda è vecchia, l'OP ha menzionato XP e anche Python, C o C ++, ma ho scoperto che molte informazioni in rete su questo argomento sono incomplete o errate. Un esempio di quest'ultimo è il suggerimento di utilizzare WMI, in particolare la classe Win32_Product ; tuttavia, come notato altrove, quel metodo è lento , in parte perché, che ci crediate o no, ogni MSI trovato effettivamente esegue la sua riparazione. La definisco errata a causa di quanto dolorosamente è lenta e del suo brutto effetto collaterale. Ad esempio, hai già optato per disabilitare il servizio Windows di un programma ma chiamando select * da Win32_Product , come parte della garanzia che la riparazione MSI venga eseguita, apparentemente riattiverà il servizio.

Per quello che vale, di seguito è quello che considererei l'esempio più completo fino ad oggi, anche se in C # (l'ho compilato con Framework 4.6.1 ma anche le versioni inferiori potrebbero funzionare). Elenca 32-bit e 64 -bit programmi installati; dispone delle chiavi di registro che utilizza e viene eseguito in meno di un secondo, almeno dopo l'attivazione della cache. Se puoi offrire miglioramenti, ti preghiamo di suggerirli invece di effettuare solo il downgrade e aggiornerò il codice.

Una cosa che manca è ancora alcuni aggiornamenti. Ad esempio, quando lo eseguo sul mio sistema Windows 10 e lo confronto con il Pannello di controllo | Programmi e funzionalità | Aggiornamenti installati, noto che non mostra Aggiornamento di sicurezza per Adobe Flash Player per qualche motivo.

Non ho alcuna buona ragione per il metodo anonimo, è proprio come pensavo in quel momento - una sorta di soluzione metodo-in-un-metodo.

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

[Sospiro] e poi ho visto la risposta di @ PolyTekPatrick. Come mi sono perso? LOL

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top