كيف يمكنني تعداد/سرد جميع التطبيقات المثبتة في نظام التشغيل Windows XP؟

StackOverflow https://stackoverflow.com/questions/802499

سؤال

عندما أقول "التطبيق المثبت"، أعني في الأساس أي تطبيق مرئي في [لوحة التحكم]->[إضافة/إزالة البرامج].

أفضّل أن أفعل ذلك بلغة Python، لكن لغة C أو C++ مناسبة أيضًا.

هل كانت مفيدة؟

المحلول

إذا كنت تعني قائمة التطبيقات المثبتة التي يتم عرضها في إضافة \ إزالة البرامج في لوحة التحكم، يمكنك العثور عليها في مفتاح التسجيل:

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall

مزيد من المعلومات حول كيفية بناء شجرة التسجيل يمكن العثور عليها هنا .

وتحتاج إلى استخدام winreg API في بيثون لقراءة القيم من التسجيل.

نصائح أخرى

وتحقق من Win32_Product WMI (ويندوز الأجهزة الإدارية) فئة. إليك تعليمي على استخدام WMI في بيثون.

تستخدم لوحة التحكم Win32 COM API، وهي الطريقة الرسمية (انظر مجموعات Google، Win32)
لا تعتمد أبدا على التسجيل.

ووالبرامج النصية ل 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

وتنفيذ المستندة إلى التسجيل أفضل ما رأيت هو أحد كتبه كريس رايت (chris128) نشرت على الموقع http://www.vbforums.com/showthread.php؟t=598355 . ويستخدم مفاتيح التسجيل متعددة وهو الكثير أكثر تعقيدا من أي من الإجابات نشر إعلان هنا. على ما يبدو لتحقيق نتائج مماثلة لإضافة التطبيق / إزالة البرامج، ومثل ARP app وأنه يوفر أيضا خيار لتشمل التحديثات.

وعلى الرغم من انها تنفذ في VB.NET، فإنه ينبغي أن يكون من السهل تحويلها إلى لغات NET الأخرى مثل C # أو و IronPython. أتصور أن تحويل لو IronPython أولا أن تجعل من السهل إلى حد ما إلى الميناء لبيثون العادية اذا كان هذا ما تريد، ولكن أنا تحويلها فقط إلى C # نفسي ومن ثم تنظيف رمز قليلا.

وعلة واحدة صغيرة فقط أن نشير إلى: GetUserInstallerKeyPrograms () لا يضيف النسخة لبرامج المستخدم إلى قائمة، على الرغم من أنها تستخرج منه. هذا أمر سهل لإصلاح بالرغم من ذلك.

وC # رمز الصافية للحصول على قائمة البرامج المثبتة باستخدام WMI في إكس بي و 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"]);
        }

وأعرف أن هذا السؤال هو القديم، ذكر OP XP وكما ذكر بيثون، C أو C ++ ولكن وجدت أن الكثير من المعلومات على شبكة الانترنت حول هذا الموضوع هو إما ناقصة أو غير صحيحة. مثال على هذا الأخير هو اقتراح لاستخدام WMI - على وجه التحديد، فإن الطبقة Win32_Product. لكن، وكما لوحظ في أماكن أخرى، وهذا الأسلوب هو بطيئة ، ويرجع ذلك جزئيا، صدقوا أو لا تصدقوا، كل MSI تم العثور عليها في الواقع تدير إصلاحه. أدعو أن الحل غير صحيحة بسبب الطريقة بطيئة بشكل مؤلم كما هي، ولما له من سيئة الآثار الجانبية. على سبيل المثال، كنت قد اخترت عدم تعطيل خدمة Windows برنامج لكنه يدعو select * from Win32_Product، كجزء من ضمان إصلاح MSI يعمل، على ما يبدو إعادة تمكين هذه الخدمة.

لما يستحق، وفيما يلي ما يمكن أن نعتبر أن يكون المثال الأكثر اكتمالا حتى الآن، وإن كان ذلك في C # (أنا جمعت ضد الإطار 4.6.1 ولكن الإصدارات أقل قد تعمل أيضا.) وهو يسرد 32 بت و 64 بت البرامج المثبتة. تصرفت مفاتيح التسجيل التي يستخدم وتشغيله في أقل من ثانية واحدة، على الأقل بعد التخزين المؤقت جزاء. إذا كنت يمكن أن تقدم التحسينات، يرجى توحي لهم بدلا من مجرد downvoting، وسوف أقوم بتحديث التعليمات البرمجية.

وشيء واحد هو هو يزالون في عداد المفقودين هو بعض التحديثات. على سبيل المثال، عند تشغيل على بلدي نظام ويندوز 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 ل. كيف افتقد ذلك؟ LOL

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top