I am enumerating installed applications using WMI, and this block is taking a relatively long time to complete no matter how I structure it. It takes 13 seconds in my environment every time. Is there a better (faster) way to check if a program is installed? (I'm using iTunes as an example program to check for)
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 WHERE name 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 WHERE name LIKE 'iTunes'
0 - 08:19:53.9144
1 - 08:19:53.9324
2 - 08:19:53.9394
3 - 08:20:07.2794
Length - 1
WMI is taking it's time as you already noticed. Iterating through the registry might do the trick for you.
You might have a look at Get installed applications in a system here on stackoverflow, where both methods are mentioned.
If you query "Win32_product" the msi-installer checks and validates every product.
The KB article http://support.microsoft.com/kb/974524 shows:
So be careful with "Win32_product".
Update: nice article https://sdmsoftware.com/group-policy-blog/wmi/why-win32_product-is-bad-news/
As Bernhard points out, WMI use of Win32_Product initiates an integrity check of the package estate, and will hence be quite slow to use - and in special cases it can trigger an MSI self-repair (I have never seen this happen on my machines).
Instead of WMI, you can use the MSI automation interface directly to enumerate the applications installed via Windows Installer packages (MSI files) on the machine. This is very quick and doesn't touch WMI at all.
See this example: how to find out which products are installed - newer product are already installed MSI windows (full blown, but basic and easy to understand VBScript example - do check it out). There are many properties you can retrieve for each product, please consult the MSDN documentation for the MSI automation interface. The linked sample VBScript code and the MSDN documentation taken together should help you get going quickly I hope.
P.S: I know this is an old question, but this issue keeps coming up (specifically the slowness of WMI) - just for future reference.
You Should use
SELECT Name FROM Win32_Product
in WMI Query, it works for meSELECT *
make Load all Data Members, so using it are taking much timeAs mentioned here Registry is not reliable and WMI is slow. Thus for me the best option was using Windows Installer API. Add msi.dll to your references and then adapt the following code to your needs: