Win32_Product WMI Class Replacement Print E-mail

Using the Win32_Product WMI class to inventory installed MSI products does some very unexpected and nasty things.  If you are using this class locally to retrieve product data we have a replacement that is not only much safer, it is a million times faster (roughly).



Ok, I admit we were using Hyperbole Metrics to come up with the speed estimate, but I am sure the speed difference will dazzle you :)

Last week I joyously published a small article on the new properties available in the Win32_Product WMI class.  My intention was to point out that some of the new properties could make writing scripts for local checking of version numbers easier than using the WindowsInstaller.Installer object because there would be fewer lines of code and there is much more general famliarity with using WMI access methods (e.g. there is no "scriptomatic" for the WindowsInstaller.Installer object).

I was gently reminded by Angie Stahl of Dell that the Win32_Product class triggers the mysterious Windows Installer "consistency check".  She cross referenced a couple web articles, however, over email she shared an experience using Win32_Product that proved out how dangerous enumerating this class could be if one is running the script on many desktops or servers.

Well, what if you intend to only grab the version number of one product, then it should just consistency check that one product and that's not a big deal right?  Wrong.  It does the consistency check on many, many packages.  How many?  Well, as I mentioned, it is a mysterious process and there is no way to predict it.

Now if you're like me, right about now you're thinking either "prove it" or "I want to see it for myself" (Which may partially explain why you read uber-geeky websites with names like "CSI-Windows").

Got an ELEVATED command prompt handy?  Hit it with this:

    wmic product WHERE "Name like '%office%'" get

All the packages with the word "office" in their descriptive name will be listed.  You could force this to just one package - but I wanted to make sure the sample gets something on most any machine.

Now there are two places you can find the evidence.  The "Application" event log, Event ID 1035 and the WINDOWS temp folder (not the user profile temp folder).  You will find one 1035 event for each MSI installed package on your system.  If you have the Windows Installer logging policy turned on, you will find one .LOG file for each package.  If you open any of them, the first line will show the starting process to be wmiprvse.exe.

The above query includes a wild card which has to search every item, so you might be thinking a direct query wouldn't generate a touch to each MSI package.  Here is an example command line that retrieves only one product, but touches every package (this is Office 2010 Standard, you may need to find a ProductCode on your machine for a valid test):

    wmic product WHERE "IdentifyingNumber = '{91140000-0012-0000-0000-0000000FF1CE}'" get

Keep in mind it is the Win32_Product class that has this behavior - so it does not matter how you access the class - VBScript, PowerShell, SCCM Inventory, compiled code, etc, etc. - the same behavior will occur.

To devise a solution for local scripting (not over the network like WMI)  I had to way-back machine and dust off some old code.


Many, many years ago an operating system called Window XP was released.  It contained Windows Intaller 3.0.  Windows Installer 3.0 contained new scripting APIs for enumerating Windows Installer products - with many cool enhancements.  However, no sample code for these APIs shipped with the production SDK.  The one sample available on the 3.0 Beta (WiLstPrdEx.vbs) did not show off the new capabilities of the new APIs - by default it operated just like it's 2.0 predecessor.

So I dug into the sample code we've had under wraps in our Scripting and Custom Actions class for over 6 years to create a solution for this problem.

In the attachment to this article is VBScript code to help with this problem.  The direct Windows Installer scripting APIs has the following benefits over the WMI Class:

  • Does not trigger the mysterious MSI consistency check.
  • Is much faster than the Win32_Product class.
  • Allows enumeration of products in all three MSI "install contexts" - 1) Per-Machine, 2) Per-User Managed (installed by GPO or the like), 3) Per-User Unmanaged for Current User ONLY (Software the end user installed only for themselves).  

    For those who are unfamiliar with installation contexts the SAME product can be multiple install contexts.  For instance, Per-User Managed for more than one user or Per-User and Per-Machine (as long as the per-machine was installed SECOND and using a different user profile than the per-user was installed under).

The attachment contains three scripts which all do things a little differently (all designed for cscript.exe execution from an elevate command prompt):

  • CSI_Win32_ProductReplacement-simplified.vbs - if you are interested in understanding how this works and/or comparing it to standard code for the Win32_Product, this is where to start.  HOWEVER it is meant as a learning script only - a bunch of coding you would have to do around it, is already done for you in the next script.
  • CSI_Win32_ProductReplacement.vbs - this code creates a function that can do anything from listing all install properties for all products in all installation contexts to outputing ONLY the value of a single property for a single installed package in a specified install context.  It can also tell you if a product is not installed.  Sample calls to the function are included.  This code could be included in a locally running "installation control" script or a custom action to investigate the versions of installed products or determine if they are installed at all.
  • CSI_WMICProductListReplacements.vbs - the name of this script is a little deceiving - it is intended to be used interactively at the command line to list products in various install contexts.  Please consult the scripts help information via the question mark argument: "cscript CSI_WMICProductListReplacements.vbs /?"

So if you have a scripting project that involves enumerating Windows Installer packages, skip Win32_Process and grab a copy of CSI_Win32_ProductReplacment.vbs.

Additional Info:

Why Win32_Product is Bad News! (

Win32_Product is Evil (

Event log message indicates that the Windows Installer reconfigured all installed applications (
Download this file ([ ]8 Kb