This entry isn’t strictly related to Group Policy, but something I came across in that context a few days ago. There is a WMI class called Win32_Product. Querying this class lets you enumerate all installed MSI applications on a given system. This might sound useful for, say, a Group Policy WMI filter. You might be tempted to use it to create a conditional Group Policy scenario whereby you only process a policy if a particular application is installed. Here’s why that would be a bad idea. First off, Win32_Product is one of those horribly un-optimized WMI providers. What that means is that it could take many seconds or even many minutes to complete a query such as “Select * from Win32_Product”.In other words, its dog slow. So, putting it in a WMI filter means that GP processing will wait on the completion of that dog slow query before preceding. Not a great thing.
To make matters worse, querying this class has a very annoying side effect that I just learned about, and that is documented in this KB article (http://support.microsoft.com/kb/974524). Here’s the issue. When you query this class, the way the provider works is that it actually performs a Windows Installer “reconfiguration” on every MSI package on the system as its performing the query! You can see the effect of this in the application event log with dozens of Windows Installer messages showing each installed application being reconfigured. A reconfiguration includes validating the application’s install, up to and including doing an MSI repair if there is an inconsistency found between the package and the original MSI file. This was particularly irritating in one case where I had set a policy to disable a service that was installed on the system, but whenever a Win32_Product query ran, it would “repair” the application that had originally installed that service, thus re-enabling the service! Not good.
So, the lesson here is, avoid using Win32_Product at all costs–it stinks! Also note that the Item-level targeting filter for MSI packages in Group Policy Preferences DOES NOT use this problematic class, so you’re safe there.
Darren
What do you recommend is better alternative for filtering OS version then?
Sorry, not OS, I meant app/software version
Another major drawback: this WMI class is turned off by default on Windows Server 2003 and Windows XP (requires some steps to enable in Add/Remove Windows Components – “Windows Installed WMI” feature).
Yes Aaron, that was a good question. Darren, are you aware of any good alternatives?
Mike–not sure what you mean by “turned off” but I am able to get to Win32_Product in XP just fine. Haven’t tested 2003. But, good question about alternatives. If you can use GP Preferences, then the MSI Item-Level Target in that provides a good alternative. If not, and you’re stuck with WMI filters, then you have to find another class that can represent some part of your app. For example, if the app puts shortcuts on the system, you could use Win32_Shortcut or Win32_LogicalProgramGroupItem. I’ve seen folks try to use Win32_DataFile but that means you are enumerating every file on a system–not great. And of course, the registry provider does not lend itself to WMI filters because it can’t be represented as a WQL query. Again, if you don’t need to use a WMI filter, you could script this into a startup or logon script (of course at that point you would probably be better served using GP Preferences). So, not a ton of great answers unless you can use GPP
Darren,
I have had some pretty “dog slow” experiences with Win32_Shortcut as well. It is actually used in a Microsoft authored Office 2007 uninstall script I was looking at the other day. We kept trying to figure out why the wscript.exe process would never terminate and it was because they were using Win32_Shortcut to do part of the cleanup. I let the query run on my system through lunch last week and it never did finish, so stay away from it too, or at least take heed before using.
good info Jamie. I suspect you’re right about the Win32_ShortcutFile class. Anything that is going to search the whole disk is going to be less than optimal. I ran a test on my machine and it took about a minute to enumerate all the shortcut instances–not great.
I discovered this a long time ago when I wanted to deploy the .NET Framework 3.0 and higher via GPO. Because 2.0 is a pre-req for 3.0 and 3.0 is a pre-req for 3.5, I tried using a WMI filter based on Win32_Product.
Never mind the unintended _result_ of MSI repairs. I could live with that. After all, the whole point of repair is to ensure the integrity of an installation. If you have deployed an MSI that enables a service you don’t want to be enabled, you should have deployed it with an MST (transform) rather than relying on post-install policy to disable it.
To me, the nastiest part of Win32_Product enumeration is the enormous CPU utilization required on machines where the Windows Installer database is large (in other words, machines where many small and/or a few large MSI packages had been installed). In particular, machines with Visual Studio or products which redistribute the Visual Studio IDE (such as SQL Server 2005 and later) would max the CPU for several minutes. On machines jammed into poorly ventilated spaces, the CPU overheat was enough to cause blue screens.
But wait, that’s not all. All my WS2003 boxes have the WMI Provider for MSI, which Mike has already pointed out is necessary for querying Win32_Product. Guess what? If your WS2003 box has a large Windows Installer database, you also better have the KB925336 hotfix (which is NOT delivered by Automatic Updates so not typically found in the wild). Otherwise, your server may go into a loop doing MSI repairs (every time background refresh of GPO happens, because WMI filters apply to the entire GPO, even if the only purpose of the filter relates to MSI deployment which happens only at boot). Aside from the CPU waste, every repair leaves an MSI*.LOG file in your system %TEMP% path (which, by default, would be on your boot volume). Each file may be small, but if this goes unnoticed for a couple of months, you can easily run out of space on your boot volume, which is always lots of fun. (KB925336 wasn’t specifically for this scenario, but that’s the hotfix which happens to address it.)
I think Microsoft discovered this danger sometime between 2001 and 2003, which is why the WMI Provider for MSI was a standard part of XP but an optional component in WS2003. I just wish Microsoft would have openly documented it.
Great feedback Ronny!
Are there plans in Microsoft’s roadmap to optimize WMI for more reliable and efficient performance?
If so, when and how?
If not, why not?
Darrick-
You’ll have to ask Microsoft that.
Excellent Post ! Thanks for this.
We have same issue “Windows Installer “reconfiguration” on every MSI package on the system as its performing the query”. Can somebody helps ,how to resolve the issues in XP.Also want to know what should be alternate to Win32_product ?
I was really exited when I found the uses of WMI and powershell, and how my current scripts could be reduced just to a couple of lines. This was until I actually test them and start investigating why my scripts were so different in terms of performance.
And was then that I discovered the “reconfiguration” issue. So think for the time being I’ll go back to my previous option, querying the registry:
Reg Query HKLMSOFTWAREMicrosoftWindowsCurrentVersionUninstall
oh, in my case, I was working on a script to automatically uninstall specific products.
Thanks for the post,
D
Hi
Speaking abot win32_product…. Read this http://csi-windows.com/toolkit/win32product-replacement
Regards
Alex
Thanks for this post, it’s very helpful.
I just wanna query all applications installed on a system but found this query so slow.
It will be a better idea to use functions “MsiEnumProducts” and “MsiGetProductInfo” in “msi.h”/”msi.lib”/”msi.dll”.
Thanks,
Andy Cui
i want to access the path of process to run process automatically by using that path. But i don’t know this will be done? some one have any idea. And remember i am codding in java(Hint in C# we this class ManagementObjectSearcher)
thanks
gwmi win32reg_addremoveprograms
If you have SCCM 2012 its good and take a few milliseconds
$app = Get-WmiObject -Class Win32reg_addremoveprograms | Where-Object {
$_.name -like “Adobe*” }
$app.uninstall()
la Clase Win32_Product puede ser de mucho provecho, claro si usted se lo propone. Si Win32_Product es demasiado lenta cuando se consulta, preguntese ¿porque no almacenar el resultado de esa consulta?
This is an old thread but a common issue when looking for installed software or the uninstall string. Posting this in the event someone comes upon this post.
See this link for details, look at the solution at the bottom posted by pwshliquori
https://powershell.org/forums/topic/working-with-registry-properties-noteproperty/
This code returns the info for both the x32 and x64 software installed. Short and simple. It can also be used with Invoke-command as a scriptblock to query many servers at once.
”,’Wow6432Node’ |ForEach-Object {
Get-ItemProperty HKLM:\SOFTWARE\$_\Microsoft\Windows\CurrentVersion\Uninstall\VMware* |
Select-Object DisplayName,DisplayVersion
}