Compliance Items and Compliance Baselines in ConfigMgr is so powerful! And with some PowerShell magic you can almost use it to do anything you like on a Windows based computer – Only your imagination that will be the showstopper!
Here I will show how you can uninstall software using WMI and Compliance Items in SCCM. However, it is important that you read the following articles as the uninstallation process uses win32_product WMI class which is known for its evilness. Thanks to Kaido, Jürg and Torsten for pointing this one out. A updated post as been created using a better and more reliable way of doing this with the SMS_InstalledSoftware class. Check out this post for a better way and instructions: http://bit.ly/1N3xwLQ
Win32_Product is evil:
- http://gregramsey.net/2012/02/20/win32_product-is-evil
- http://blogs.catapultsystems.com/cnackers/archive/2012/02/20/win32_product-is-evil
- http://blogs.technet.com/b/askds/archive/2012/04/19/how-to-not-use-win32-product-in-group-policy-filtering.aspx
If you want to play with the Win32_Product class anyway follow these steps however it is not recommended for production:
Well, I had a customer that wanted me to 1. Identify all computers running any Java applications and 2. uninstall it if it existed. I quickly told about Compliance baselines which can
- Discover java and report non-compliance
- Remediate non-compliance by uninstalling Java
- Report back compliance
all in one operation. 30 minutes later we had a working solution which we deployed to the organization.
Let’s start by creating the CI in your ConfigMgr Environment
On The server:
Detection Script:
#Detect Software Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -match "Java"}
Remediation Script:
#Uninstall Software $app = Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -match "Java" } foreach ($a in $app) {$a.Uninstall()}
Now that we have a working Compliance Item we can create a Compliance Baseline which is based on the CI we just created.
Click OK, rigth click the baseline and choose deploy.
Choose that you want to Remediate noncompliant rules. Select appropriate collection and a suited schedule.
One the Client:
Next is to go to the client and check if the CI and Baseline is doing what it’s supposed to to. Just so you know I am not cheating – check out the screenshots below which shows Java installed and then uninstalled after running the rules.
Java installed:
Compliance baseline is unknown or Non-Compliant
Java is uninstalled automatically:
Let’s work together for a more secure environement without Java – Cheers!
Hi Marius
Ever watched what happens in your Application Eventlog, if you query the Win32_Product Class? This Class is evil. (take a Web search on “Win32_Product Evil” and you will find a lot of Entries, e.g. this http://blogs.technet.com/b/askds/archive/2012/04/19/how-to-not-use-win32-product-in-group-policy-filtering.aspx
With the CM Agent installed, activate the Asset Intelligence Classes and take the SMS_InstalledSoftware Class instead
Kind regards
Jürg
Yes, but the SMS_InstalledSoftware class does not define any methods. https://msdn.microsoft.com/en-us/library/cc144824.aspx
So you could query if the software is installed (Like below example), but not uninstall it with a method like .Uninstall. If I am correct.
#Detect Software
Get-WmiObject -Query “SELECT * FROM SMS_InstalledSoftware” -Namespace “rootcimv2sms” | Where-Object {
$_.ProductName -match “Java”}
However I will moderate/change the post and also see if I can come up with a alternative solution. Thanks for tip! 🙂
This is clever, but wouldn’t it remove all, even the newest java?
Tis is true. It should remove any Applications named anything Java which was the purpose for this customer. If you want to remove a specific version try this instead (Java 7 Update 51 as an example):
Detection Script:
#Detect Software
Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -match “Java 7 Update 51”}
Remediation Script:
#Uninstall Software
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match “Java 7 Update 51”
}
foreach ($a in $app) {$a.Uninstall()}
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -like “Java*Update*”
}
foreach ($a in $app) {$a.Uninstall()}
Thanks for sharing!
You’re welcome! 🙂 Remember to check out Part 2 for further instructions.
http://blog.coretech.dk/mas/part-2-uninstall-java-or-any-other-software-with-configmgr-compliance-baselines/
This is great. I’m curious how you would go about removing certain versions of software that do not include the version in the product name of the software. For instance, we want to remove certain versions of a program called Zoom. We have multiple versions in our environment, but they are all named Zoom, not Zoom 3.5.1.2.
Thanks for posting this!
so it’s possible to use sms_installedsoftware, but as you mentioned, there is no uninstall method, but piping the product code into an msiexec /x works (at least for java). and consider that using a string of “java” won’t catch Java 5 and earlier as they name doesn’t include the word Java in the display name.
for your consideration:
$Product = Get-WmiObject -class SMS_InstalledSoftware -Namespace “root\cimv2\sms” |
Where-Object {($_.ProductName -like “Java*” ) -or ($_.ProductName -like “j2se*”)}
ForEach ($ObjItem in $Product)
{
$ID = $ObjItem.SoftwareCode
$Uninstall = “/x” + “$ID /qn /norestart”
$log_date = (get-date -Format g)
Start-Process -FilePath “msiexec.exe” $Uninstall -Wait
}