Win32_Product WMI Class Replacement |
![]() |
![]() |
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:
The attachment contains three scripts which all do things a little differently (all designed for cscript.exe execution from an elevate command prompt):
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! (http://sdmsoftware.com/blog/2010/04/11/why-win32_product-is-bad-news/) Win32_Product is Evil (http://www.myitforum.com/absolutenm/templates/Articles.aspx?articleid=21826&zoneid=89) Event log message indicates that the Windows Installer reconfigured all installed applications (http://support.microsoft.com/kb/974524) |