Last Updated: 2015-12-10 12:54:27 UTC
by Rob VandenBrink (Version: 1)
In my last story, we went over winnowing through a Nessus scan to determine which apps you might want to patch. But what if the final finding isn’t “Lets update Java” but rather, “Why do we need JRE installed at all? Let’s delete it across the domain”
How can you do this for free, without buying a full software inventory and management system. Say, with nothing but Powershell? In years past, I would have used WMIC and cmd files, but Powershell is much faster and much more flexible. Let’s start by listing the apps on a workstation. If you don’t have a software inventory solution, Powershell can get the job done with just a bit of scripting (note that this is does not show the entire list of members in $apps - it's a pretty long list)
Next, let’s get the info we need to delete an app – the App name, version and “IdentifyingNumber” (the application’s GUID):
OK – now let’s just pick the apps we want to remove:
That’s all the basic information we need to delete an app, let’s put it together. The $classkey variable shown is the string needed to “fully qualify” the application to delete – let’s just look at the first app in the list:
(note the escaping to make the quote characters around the values)
Then, to uninstall our target application, for each instance, we want to execute:
If $killit.ReturnValue is non-zero, the uninstall was not successful – a value of 1603 for instance means you don’t have rights to uninstall the apps, retry as local admin (or domain admin)
So, putting it all together, let’s delete a target app remotely in a typical company. We start by getting domain admin credentials (remember that you need admin rights to delete an app)
Next, get your list of servers into an object. Maybe you got that computer list from working through your Nessus report, or maybe output from your software inventory system:
Or maybe we’ll pull the target station list right out of AD. If you take this approach, maybe you just want the non-servers:
Whatever method you used to get your list, MANUALLY CHECK IT AND EDIT IT FIRST, before you proceed:
Not the most elegant piece of code, and certainly not the fastest, but it’ll get the job done. That "write-host" line especially would benefit from me making that an array of results, which would allow you at the end you to list out the full results, but then also just the failed results for instance. For me, using write-host is almost always a last resort - there's always a better option. The point was to keep things simple here though, not get to perfection - come to think of it, that's the point of most scripts we write.
Note again that this script as written can be very dangerous! We're running through a list of hosts, saying "if an application name has this string in it, delete it immediately". If you pick the wrong string (say "advanced" or "microsoft"), you could match a lot more than you intend to! Given that this script is going to UNINSTALL apps across your domain, and maybe reboot machines along the way, you likely will not want this in one mondo – automagic script anyway. Dumping things out, checking output along the way and testing step by step is definitely the way to go. Running your version of this against a few test stations first is also a really good practice.
This might sound like a lot of manual Posershell steps, when there's a script right there - but it’s still way faster than having to recover an app after you’ve had a script like this run through your domain. And needless to say, it's also way faster than uninstalling apps from stations one-by-one using just your keyboard and RDP!
If you’ve got a neat trick for uninstalling apps, or better yet, if you’ve got a more elegant Powershell approach for this, by all means, please share in our comment section!