Using PowerShell to Uninstall Applications with Hardware Inventory
Last year I told you about how I needed a script that would detect all versions of an application on a computer and uninstall each version one at a time. Long story short, I couldn’t find one, so I ended up putting one together! Since the original post was published, I received a number of questions about how to force a delta or a full SCCM hardware inventory after the applications were uninstalled. Eventually I decided to update my original script and the post about using PowerShell to uninstall applications.
The new script includes a delta inventory and there is now an option to force a full SCCM hardware inventory. Previously, if the uninstalled application was an EXE file (and not a MSI file) the PowerShell script would fail because the hard code would only allow MSI files to uninstall. I corrected this problem, so now both EXE and MSI files are uninstalled.
Before getting to that, though, I should tell you that my friend Jason Sandys already had a VBScript to do exactly what I was looking for last year. There is a long inside joke between us about VBScript vs PowerShell, but I won’t bore you with it here. When I was originally looking for scripts, it had to be PowerShell or nothing. At the time the reason was simple. I needed to learn more about PowerShell, so I never looked for a VBScript and never saw Jason’s post. The funny part is that Jason eventually told me about his script and showed me one very cool feature. You can force a hardware inventory cycle to occur afterwards! You must check out Jason’s script on his blog site.
I can hear some of you saying, “Which script is better?” The answer depends, in my opinion, on your understanding of VBScript and PowerShell. Outside of that, pick the one you like the best and use it!
I was product testing Monitor Information Reporting (MIR) which is now a part of Enhansoft Reporting. This testing involved deploying several updates to my lab’s clients. My lab’s a mix of both x86 and x64 operating systems (OS). After deploying all of these versions of MIR, I was left looking for a solution that would enable me to quickly clean-up the client installs. Ultimately I only wanted the final version of MIR installed on each client.
Unfortunately there was no way of knowing which versions of MIR were deployed to which test computers. There was also the possibility that several test computers could have more than one version of MIR installed. I needed an easy way to automatically detect all versions of MIR on a computer and uninstall each one, one at a time, without having to manually uninstall it on each computer. Since this time, I am happy to say, the setup for MIR was updated, so only one version of it can be installed on a computer at a time.
Back to last year’s problem. You would think that I could find a PowerShell solution. Have you ever deployed Adobe Reader? Then you would know that there can be several different versions of Adobe Reader listed within Add/Remove Program (ARP) on a computer. Why wouldn’t there be an easy way to delete the older versions?
I found a lot of PowerShell scripts that would help me uninstall only one application at a time. There were even a few PowerShell scripts out there that would query Win32_Product and then uninstall two or more applications. If you, however, read Greg Ramsey’s blog post Win32_Product Is Evil you would know that this is a bad idea. You should never do that! That’s why I could never use Win32_Product within my script due to the problems it creates.
Using PowerShell to Uninstall Applications
At a high-level, this is what my updated PowerShell script does:
-Detects if the script is running in x84, x64 or WoW32 mode.
-Reads both x86 and x64 uninstall registry keys.
-Locates all versions of an application.
-Loops through the list of ARP entries and collects the:
-MSI name/GUID/Uninstall string.
-Detects if the application is an EXE or MSI and uninstalls the application accordingly.
-Logs each step to a log file.
-Runs a delta hardware inventory or, if the flag is set, a full SCCM hardware inventory.
Below is what the final script looks like, but you can also download it from the Enhansoft website.
Force a Full SCCM Hardware Inventory
By default, a delta hardware inventory cycle will start as one of the last steps within the script. There is nothing more that you need to do. I like to force, however, a full inventory when I uninstall applications. If you’re like me, then all you need to do is change the $fullinventory = $false value to $true. This will force a full SCCM hardware inventory to occur.
How to Deploy the Uninstall Application Script with SCCM
First, start by editing the script. Replace the application’s name with the one you want to uninstall. In the download version it is currently set to: Monitor*Information*Reporting* Keep in mind that the * is a wild card used to search ARP entries.
Second, decide if you want to force a full SCCM hardware inventory, so set the flag accordingly.
Third, create a package and program for your command line. It should look similar to the following:
powershell.exe -ExecutionPolicy bypass -file Uninstallv10.ps1
Fourth, and finally, deploy the package and program as you would any other program.
Using the Uninstall Application Script
You can see in the screenshot below that I had several copies of MIR installed on this test computer last year.
I setup my program to silently deploy in the background. Nothing to see from an end-user’s perspective!
If you would like to verify that the PowerShell script is running, look at the Task Manager. You’ll have to be quick! The script only takes a few seconds to a few minutes to run depending on the number of ARP it has to remove. As an aside, you can also see that the script ran within the Execmgr.log on your test computer.
You can see from the screenshot above that after a few minutes all of the Monitor Information Reporting ARP entries were removed.
Keep in mind that the hardware inventory cycle (delta or full) will start soon after all of the applications are uninstalled. It only takes a few seconds to run (~60 seconds).
In some cases, you might want to reboot the computers after the hardware inventory is submitted to SCCM. In my case, I added a Sleep command to the PowerShell script for 75-seconds before rebooting. If your hardware inventory takes longer, simply adjust the time accordingly.
Here are the commands I used:
Start-sleep – seconds 75
If you have any questions about using PowerShell to uninstall applications, please contact me @GarthMJ.