Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Как я могу перечислить / перечислить все установленные приложения в Windows XP?

Автор вопроса: sharkinОтветов: 7

Когда я говорю "установленное приложение", я в основном имею в виду любое приложение, видимое в [Панель управления] -> [Установка и удаление программ].

Я бы предпочел сделать это на Python, но C или C ++ тоже подойдут.

  • Как вы определяете установленное приложение? 29.04.2009

pythonc++winapienumeration

Ответы

Ответ 1 · рейтинг 12 · Aziz

Если вы имеете в виду список установленных приложений, который отображается в разделе "Установка и удаление программ" панели управления, вы можете найти его в разделе реестра:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall

дополнительную информацию о структуре дерева реестра можно найти здесь.

Для чтения значений из реестра необходимо использовать winreg API в Python.

Ответ 2 · рейтинг 10 · Tamas Czinege

Ознакомьтесь с Win32_Product WMI (инструментарий управления Windows) класс. Вот руководство по использованию WMI в Python.

Ответ 3 · рейтинг 8 · Community

Панель управления использует Win32 COM api, который является официальным методом (см. Группы Google, Win32)
Никогда не полагайтесь на реестр.

Ответ 4 · рейтинг 7 · John Fouhy

В репозитории сценариев Microsoft есть сценарий для вывода списка всего установленного программного обеспечения.

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

Ответ 5 · рейтинг 6 · PolyTekPatrick

Лучшая реализация на основе реестра, которую я видел, - это написанная Крисом Райтом (chris128), размещенная по адресу http://www.vbforums.com/showthread.php?t=598355. Он использует несколько ключей реестра и намного сложнее, чем любой из ответов, опубликованных в настоящее время здесь. Кажется, что оно дает те же результаты, что и приложение "Установка и удаление программ", и, как и приложение ARP, оно также предоставляет возможность включать обновления.

Хотя он реализован в VB.NET, его должно быть легко преобразовать в другие языки .NET, такие как C # или IronPython. Я полагаю, что преобразование в IronPython в первую очередь должно упростить перенос на обычный Python, если вы этого хотите, но я только сам преобразовал его на C #, а затем немного очистил код.

Следует отметить только одну небольшую ошибку: GetUserInstallerKeyPrograms () не добавляет версию для пользовательских программ в список, хотя и извлекает ее. Однако это легко исправить.

Ответ 6 · рейтинг 3 · mujjiga

Код C # .net для получения списка установленного программного обеспечения с использованием WMI в xp и win7 (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"]);
        }

Ответ 7 · Craig Silver

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. Как я это пропустил?

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы