A member on the TechNet forums asked a question why a certain PowerShell script was not working on virtual machines, but it worked on physical. The member didn’t provide the whole script, but basically the primary function was to initiate a uninstall of an application in Software Center. I started wondering how hard it could be to actually accomplish this, these are my findings.
To see what applications are currently detected as installed and shown in Software Center, we’d have to explore WMI. The class we’re interrested in is CCM_Application. That class is available in the root\ccm\clientSDK namespace. In this post we’ll be uninstalling an application called XML Notepad 2007 that an user has installed from the Application Catalog.
We’ll begin with setting two variables that will be used later in the script. The first is the $ComputerName, that we set to the local machine. The $ApplicationName is set to a part of the name. It could also be the complete name of the application, if there for instance are several applications that has the “XML” in their name.
$ComputerName = $env:COMPUTERNAME $ApplicationName = "XML"
Next we create an object that we’ll use to invoke a method called Uninstall. This method is available in the CCM_Application class. In addition to that, we get the WMI object of the application we’re interested in and store that in a variable called $Application.
$ApplicationClass = [WmiClass]"\\$($ComputerName)\root\ccm\clientSDK:CCM_Application" $Application = Get-WmiObject -Namespace "root\ccm\clientSDK" -Class CCM_Application | Where-Object { $_.Name -like "*$($ApplicationName)*" }
After we’ve retrieved the WMI object of the application, we store the ScopeID (retrievable in the property called Id of the application WMI object) in a variable called $ApplicationID. Next up we store the Revision in a variable called $ApplicationRevision.
$ApplicationID = $Application.Id $ApplicationRevision = $Application.Revision
We now have all the necessary information in order to actually invoke the Uninstall method. But, before we do that, let’s talk bit more about the method itself. You can read more about the method here:
https://msdn.microsoft.com/en-us/library/jj885507.aspx
The method wants 6 arguments when invoked. These arguments are the following:
- Id (String, Id property of the application WMI object)
- Revision (String, Revision property of the application WMI object)
- IsMachineTarget (boolean)
- EnforcePreference (Integer, 0 = Immediate, 1 = NonBusinessHours, 2 = AdminSchedule)
- Priority (String, can be either “Normal”, “High”, “Low” or “Foreground”)
- IsRebootIfNeeded (boolean)
We already have the Id and Revision stored in variables, now we need to find out the rest.
IsMachineTarget
If we run the following code:
Get-WmiObject -Namespace "root\ccm\clientSDK" -Class CCM_Application | Where-Object { $_.Name -like "*XML*" } | Select-Object IsMachineTarget
From the output we’ll get either True or False. What’s really happening here is if the application was deployed to a device collection, the output of the command above would be True. If the application instead was deployed to a user collection, the value would be False. Since we’re working with an application deployed to a user collection, we now know that the IsMachineTarget argument should be False.
EnforcePreference
EnforcePreference is quite self explanatory. Do we want to uninstall the application immediately, or more controlled. In this post we’ll uninstall the application immediately. So we should set the EnforcePreference to 0 (zero).
Priority
This argument is also quite easy to decide. Lets use High so we can uninstall it quickly. It’s a nasty software!
IsRebootIfNeeded
If we set this argument to True, the ConfigMgr agent will enforce a system restart. In this post we don’t want to do that, so we’ll set it to False.
With all this information known to us, we can now write the last line of code in this script:
$ApplicationClass.Uninstall($ApplicationID,$ApplicationRevision,$false,0,"High",$false)
Conclusion
Now if we put all the pieces together, we should have the following script:
$ComputerName = $env:COMPUTERNAME $ApplicationName = "XML" $ApplicationClass = [WmiClass]"\\$($ComputerName)\root\ccm\clientSDK:CCM_Application" $Application = Get-WmiObject -Namespace "root\ccm\clientSDK" -Class CCM_Application | Where-Object { $_.Name -like "*$($ApplicationName)*" } $ApplicationID = $Application.Id $ApplicationRevision = $Application.Revision $ApplicationClass.Uninstall($ApplicationID,$ApplicationRevision,$false,0,"High",$false)
Save the above script as e.g Remove-SoftwareCenterApplication.ps1 and run it non-elevated. The application will now be uninstalled from the computer.
How about one to install a specific app?
Why wouldn’t you get IsMachineTarget from the Application object the same way you get Id and Revision?
It was merely to demonstrate how to get it. You could create an if condition based on the value of IsMachineTarget and proceed or not.
Regards,
Nickolaj
How can I get Application List for Client using c#.
Hi
Will this work if the application is deployed with an ”required” deployment? I have been testing this on a client with SCCM 2012 R2 CU3. I can see the application in WMI. When I run the script I get back:
__GENUS : 1
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH : __PARAMETERS
__PROPERTY_COUNT : 2
__DERIVATION : {}
__SERVER : T310
__NAMESPACE : ROOT\ccm\ClientSDK
__PATH : \\Client01\ROOT\ccm\ClientSDK:__PARAMETERS
JobId : {A61AA1D7-00F2-4C42-926C-5FB8D3503714}
ReturnValue : 0
PSComputerName : Client01
I change the scrip to device instead of user.
Regards
Mikael
Hi Mikael,
I’ve not verified myself, but I’m assuming that I’d get the same results that you’re seeing. Since you’re trying to force the uninstall of a Required Deployment, even though the method called returns 0, it would not work.
Regards,
Nickolaj
Any suggestion how to uninstall a required application/deployment?
Thanks in advance
Fantastic post. I was having some issues installing software with this class and your post helped out perfectly.
Hi Paul,
That’s great! I’m glad that you were able to work it out, have a great one! 🙂
Regards,
Nickolaj