WMI - выбор из Win32_Product занимает много времени - программирование

WMI - выбор из Win32_Product занимает много времени

Я перечисляю установленные приложения с использованием WMI, и этот блок занимает относительно много времени, чтобы завершить, как бы я его не структурировал. Каждый раз это занимает 13 секунд. Есть ли лучший (более быстрый) способ проверить, установлена ​​ли программа? (Я использую iTunes в качестве примерной программы для проверки)

    private static string Timestamp
    {
        get { return DateTime.Now.ToString("HH:mm:ss.ffff"); }
    }

    private static void LoadInstalledPrograms()
    {
        List<string> installedPrograms = new List<string>();
        Console.WriteLine("0 - {0}", Timestamp);
        ManagementObjectSearcher mos = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
        Console.WriteLine("1 - {0}", Timestamp);
        ManagementObjectCollection managementObjectCollection = mos.Get();
        Console.WriteLine("2 - {0}", Timestamp);
        foreach (ManagementObject mo in managementObjectCollection)
        {
            installedPrograms.Add(mo["Name"].ToString());
        }
        Console.WriteLine("3 - {0}", Timestamp);
        Console.WriteLine("Length - {0}", installedPrograms.Count);
    }

SELECT * FROM Win32_Product

0 - 08:08:51.3762
1 - 08:08:51.3942
2 - 08:08:51.4012
3 - 08:09:04.8326
Length - 300

SELECT * FROM Win32_Product WHERE name = 'iTunes'

0 - 08:14:17.6529
1 - 08:14:17.6709
2 - 08:14:17.6779
3 - 08:14:31.0332
Length - 1

SELECT * FROM Win32_Product ГДЕ имя LIKE 'iTunes'

0 - 08:16:38.2719
1 - 08:16:38.2899
2 - 08:16:38.2999
3 - 08:16:51.5113
Length - 1

SELECT name FROM Win32_Product ГДЕ имя LIKE 'iTunes'

0 - 08:19:53.9144
1 - 08:19:53.9324
2 - 08:19:53.9394
3 - 08:20:07.2794
Length - 1
4b9b3361

Ответ 2

Если вы запросите "Win32_product" , msi-installer проверяет и проверяет каждый продукт.

В статье в статье http://support.microsoft.com/kb/974524 показано:

Класс Win32_product не оптимизирован для запросов. Такие запросы, как "select * from Win32_Product", где (например, "Sniffer%" ), требуют, чтобы WMI использовал поставщик MSI для перечисления всех установленных продуктов, а затем последовательно разбора полного списка для обработки предложения "where". Этот процесс также инициирует проверку согласованности установленных пакетов, проверки и восстановления установки. Если учетная запись имеет только пользовательские привилегии, так как учетная запись пользователя может не иметь доступа к нескольким местоположениям, это может привести к задержке при запуске приложения и событию 11708 с указанием сбоя установки.

Win32reg_AddRemovePrograms - это гораздо более легкий и эффективный способ сделать это, что позволяет избежать вызовов для проверки отказоустойчивости, особенно в закрытой среде. Поэтому при использовании Win32reg_AddRemovePrograms мы не будем вызывать msiprov.dll и не будем инициировать проверку отказоустойчивости.

Поэтому будьте осторожны с "Win32_product".

Обновление: хорошая статья https://sdmsoftware.com/group-policy-blog/wmi/why-win32_product-is-bad-news/

Ответ 3

Как упоминалось здесь Реестр не является надежным, а WMI работает медленно. Таким образом, для меня лучшим вариантом было использование Windows Installer API. Добавьте msi.dll в свои ссылки, а затем примените следующий код к вашим потребностям:

public static string GetVersionOfInstalledApplication(string queryName)
{
    string name;
    string version;
    Type type = Type.GetTypeFromProgID("WindowsInstaller.Installer");
    Installer installer = Activator.CreateInstance(type) as Installer;
    StringList products = installer.Products;
    foreach (string productGuid in products)
    {
        string currName = installer.ProductInfo[productGuid, "ProductName"];
        string currVersion = installer.ProductInfo[productGuid, "VersionString"];
        if (currName == queryName)
        {
            name = currName;
            version = currVersion;
            return version;
        }
    }
    return null;
}

Ответ 4

Вы должны использовать SELECT Name FROM Win32_Product в WMI Query, это работает для меня

SELECT * сделать загрузку всех членов данных, поэтому использование этого занимает много времени

Ответ 5

Как указывает Бернхард, использование WMI Win32_Product инициирует проверку целостности состояния пакета и, следовательно, будет довольно медленным в использовании - и в особых случаях он может инициировать самообслуживание MSI ( Я никогда не видел, чтобы это происходило на моих машинах).

Вместо WMI вы можете напрямую использовать интерфейс автоматизации MSI, чтобы перечислять приложения, установленные через пакеты установщика Windows (файлы MSI) на машине. Это очень быстро и не касается WMI вообще.

См. этот пример: как узнать, какие продукты установлены - новый продукт уже установлен Windows MSI (полный, но простой и понятный пример VBScript - проверьте его). Существует множество свойств, которые вы можете получить для каждого продукта, обратитесь к документации MSDN для интерфейса автоматизации MSI. Связанный образец кода VBScript и документация MSDN, взятые вместе, должны помочь вам быстро начать работу. Я надеюсь.

P.S: Я знаю, что это старый вопрос, но этот вопрос продолжает расти (в частности, медленность WMI) - только для справок в будущем.