In the first part of this series we looked at using WMI to identify installed applications. While I believe that is an effective method, it can be painfully slow. Fortunately, there is another path to explore and that is by searching the registry. Most applications that are installed via an installation package will record uninstalled information in the registry. There’s no guarantee of knowing if something you find in the registry is in fact still installed, and of course, not every installed application will record itself. But let’s look at how you could query this information because I’m sure more than a few of you will find it useful.

It is not too difficult to query the registry with PowerShell. However, you can only query using the Registry PSDrive on the local computer. To query remote computers, simply wrap the commands I’ll be showing you in a script block and use the Invoke-Command. In fact, let’s jump right to it, and here’s a one-line command to list names of applications that can be uninstalled.

There is a potential problem here in that some registry entries might not have a Displayname property, which will result in an error. If you are merely looking for a quick list, you can substitute the registry key name for any missing displayname properties.

Using the pipelinevariable common parameter in PowerShell to obtain more information about installed software. (Image Credit: Jeff Hicks)

My command is taking advantage of the new pipelinevariable common parameter. This parameter has an alias of pv. The end result is that the output of the directory listing is stored in $p. I can reference objects from that variable later in my expression. In my command, I am defining a new property called Path that uses the Name property of each directory item, pulled from $p.

As you look through the results, you’ll realize there are many “applications” that are merely updates, especially if you have Microsoft Office installed. What I think you will find more helpful is to filter out these applications.

PowerShell

1

2

3

4

5

$data=dirHKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall|

where{$_.name-notmatch'(\.)?KB\d+'}-pvp|

Get-ItemProperty|Where{$_.displayname-notmatch"KB\d{5,}"}|

Select@{Name="Path";Expression={$p.name}},Displayname,DisplayVersion,

Publisher,InstallDate,InstallLocation,Comments,UninstallString

My solution is to filter out using regular expression patterns, any entry that includes the string KB followed by a series of numbers. My result will be similar to the screenshot above, but without any of the update entries. The reason I saved the result to a variable is because I want to add to it. What am I adding? On 64bit machines there is another registry location to check: HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall. I am going to repeat my command using this new path and append the results to $Data.

Now I can do whatever I want with $data, and I should have a good feel what applications are installed or at least what can be uninstalled. To query a remote machine, I can wrap these commands inside a script block and use the Invoke-Command.

Finally, there is one more location in the registry where you might find this type of information and that is per user. You can use similar registry query techniques for HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall.

PowerShell

1

2

3

4

dirHKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall-pvp|

get-ItemProperty|

Select@{Name="Path";Expression={$p.name}},Displayname,DisplayVersion,

Publisher,InstallDate,InstallLocation,Comments,UninstallString

My experience with applications under HKCU is that I don’t need to filter out anything.

But there is one enormous caveat, which most of you are probably thinking about. When you run a query like this remotely, HKCU will be for the account you use to connect such as administrator. If it is a server where someone might have installed something under that account, then you could see something. But if you are checking a user’s desktop you won’t see what they installed unless you connect with their credentials, which you are probably not going to be able to do.

Next time I’ll guide you through some ways to still query the user hives.

MEMBER LOGIN:

BECOME A PETRI MEMBER:

About the Contributor

Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, teacher and consultant. Jeff has written for numerous online sites and print publications and is a frequent speaker at technology conferences and user groups. His latest book is PowerShell Scripting and Toolmaking.