Pregunta

Cuando digo "aplicación instalada", básicamente me refiero a cualquier aplicación visible en [Panel de control] - > [Agregar / quitar programas].

Preferiría hacerlo en Python, pero C o C ++ también está bien.

¿Fue útil?

Solución

Si se refiere a la lista de aplicaciones instaladas que se muestra en Agregar / Eliminar programas en el panel de control, puede encontrarla en la clave de registro:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall

más información sobre cómo está estructurado el árbol de registro aquí .

Necesitas utilizar la API winreg en python para leer los valores de el registro.

Otros consejos

Consulte el Win32_Product WMI (Windows Clase de Instrumentación de Gestión). Aquí hay un tutorial sobre el uso de WMI en Python.

El panel de control usa la API COM de Win32, que es el método oficial (ver Grupos de Google, Win32)
Nunca confíe en el registro.

El Microsoft Script Repository tiene un script para enumerar todo el software instalado.

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 mejor implementación basada en el registro que he visto es la escrita por Chris Wright (chris128) publicada en http://www.vbforums.com/showthread.php?t=598355 . Utiliza múltiples claves de registro y es mucho más complejo que cualquiera de las respuestas publicadas actualmente aquí. Parece producir resultados idénticos a la aplicación Agregar o quitar programas, y al igual que la aplicación ARP, también ofrece una opción para incluir actualizaciones.

Aunque está implementado en VB.NET, debería ser fácil de convertir a otros lenguajes .NET como C # o IronPython. Me imagino que convertir a IronPython primero debería hacer que sea bastante fácil portar a Python normal si eso es lo que quieres, pero solo lo convertí a C # y luego limpié un poco el código.

Solo un pequeño error para señalar: GetUserInstallerKeyPrograms () no agrega la versión para los programas de usuario a la lista, a pesar de que la extrae. Sin embargo, esto es fácil de solucionar.

Código C # .net para obtener la lista de software instalado usando WMI en xp y win7 (wmi es la única forma en win7)

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

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

Sé que esta pregunta es antigua, el OP mencionó XP y también mencionó Python, C o C ++, pero descubrí que mucha información en la red sobre este tema es incompleta o incorrecta. Un ejemplo de esto último es la sugerencia de usar WMI, específicamente, la clase Win32_Product ; sin embargo, como se señala en otra parte, ese método es lento , en parte porque, créanlo o no, cada MSI encontrado en realidad ejecuta su reparación. Llamo a esa solución incorrecta por lo dolorosamente lenta que es y por su desagradable efecto secundario. Por ejemplo, ya ha optado por deshabilitar el servicio de Windows de un programa, pero al llamar a select * desde Win32_Product , como parte de garantizar que se ejecute la reparación de MSI, aparentemente volverá a habilitar el servicio.

Para lo que vale, a continuación es lo que consideraría el ejemplo más completo hasta la fecha, aunque en C # (lo compilé con Framework 4.6.1 pero las versiones inferiores también pueden funcionar). Enumera 32 bits y 64 -bit programas instalados; dispone de las claves de registro que usa y se ejecuta en menos de un segundo, al menos después de que el almacenamiento en caché se inicia. Si puede ofrecer mejoras, sugiéralas en lugar de solo votar negativamente, y actualizaré el código.

Una cosa que es todavía falta es algunas actualizaciones. Por ejemplo, cuando lo ejecuto en mi sistema Windows 10 y lo comparo con el Panel de control | Programas y características | Actualizaciones instaladas, noto que no muestra Actualización de seguridad para Adobe Flash Player por alguna razón.

No tengo una buena razón para el método anónimo, es solo la forma en que pensaba en ese momento, una especie de método dentro de un 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] y luego vi la respuesta de @ PolyTekPatrick. ¿Cómo me perdí eso? Jajaja

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top