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:

http://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.

73_1

Nickolaj Andersen
Principal Consultant and Enterprise Mobility MVP. Nickolaj has been in the IT industry for the past 10 years specializing in Enterprise Mobility and Security, Windows deployments and Automation. In 2015 Nickolaj was awarded as PowerShell Hero by the community for his script and tools contributions. Author of ConfigMgr Prerequisites Tool, ConfigMgr OSD FrontEnd, ConfigMgr WebService and a frequent speaker at user groups.

(691)

comments
  • Paul
    Posted at 18:11 April 24, 2014
    Paul
    Reply
    Author

    Fantastic post. I was having some issues installing software with this class and your post helped out perfectly.

    • Nickolaj
      Posted at 18:21 April 24, 2014
      Nickolaj
      Reply
      Author

      Hi Paul,

      That’s great! I’m glad that you were able to work it out, have a great one! 🙂

      Regards,
      Nickolaj

  • Mikael
    Posted at 18:42 October 1, 2014
    Mikael
    Reply
    Author

    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

    • Nickolaj
      Posted at 13:34 October 6, 2014
      Nickolaj
      Reply
      Author

      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

      • thomas
        Posted at 11:45 September 25, 2015
        thomas
        Reply
        Author

        Any suggestion how to uninstall a required application/deployment?

        Thanks in advance

  • Thet Myo Naing
    Posted at 12:29 March 24, 2016
    Thet Myo Naing
    Reply
    Author

    How can I get Application List for Client using c#.

  • george
    Posted at 15:12 April 1, 2016
    george
    Reply
    Author

    Why wouldn’t you get IsMachineTarget from the Application object the same way you get Id and Revision?

    • Nickolaj
      Posted at 21:46 April 7, 2016
      Nickolaj
      Reply
      Author

      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

  • Leave a Reply