Executive Summary: It's important to regularly audit the applications installed on the computers in a network for a variety of reasons. You could spend some of your IT budget on purchasing a third-party application—or you can use the free Windows PowerShell script named Get-InstalledApp.ps1. Learn how to use this script and take a peek at how it works. |
System administrators often need to identify the software that's installed on the computers in their networks. It's important to regularly audit the applications installed on those computers for a variety of reasons. Administrators might install a software package, forget to document it, and later learn that a particular software package contains security vulnerabilities. End users might have the administrative permissions that allow them to install software on their computers. There's also the potential that rogue administrators can install unauthorized software and open the organization to legal liabilities.
There are third-party applications that can audit installed software, but small to mid-sized businesses might not have the resources to implement such a solution. My company didn't have a software solution in place, so I wrote the Windows PowerShell script Get-InstalledApp.ps1. Before I explain how to use this script and how it works, I want to describe two techniques for detecting installed software from a script and why I chose one technique over the other.
Win32_Product Class vs. the Registry
Windows Management Instrumentation (WMI) provides a Win32_Product class that lets you enumerate the applications installed on a computer. This is easy in PowerShell. For example, the command
Get-WmiObject Win32_Product | select name
lists all the applications installed on the current computer. However, the Win32_Product class has some limitations:
- It retrieves only the names of applications installed using the Windows Installer service. It doesn't retrieve the names of applications installed by other tools. This means that you can't use the Win32_Product class to perform a general software audit unless you use Windows Installer packages exclusively, which is an unrealistic assumption on most networks.
- Retrieving instances of the Win32_Product class is very slow.
- It's not always possible to retrieve Win32_Product class instances from remote computers. For example, when I try to do this on my own network, I get the error message Generic failure.
All these problems limit the usefulness of the WMI Win32_Product class. Fortunately, you can retrieve information about installed applications from the registry instead. The HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall registry key contains information about applications installed on a computer. Each subkey under the Uninstall key represents an installed application, and the values in each subkey contain information about the application, as Figure 1 shows. So, to get a list of applications, you can enumerate the Uninstall key and read the data in each subkey underneath the Uninstall key.
|
Figure 1: An example of a subkey under the Uninstall key (click to enlarge)
|
 |
PowerShell's registry provider lets you use the Get-ChildItem cmdlet to list the names of the applications installed on the current computer using the command
Get-ChildItem HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall |
ForEach-object { (Get-ItemProperty Microsoft.PowerShell.Core\Registry::$_).DisplayName }
However, the Get-ChildItem cmdlet can't access the registry provider on a remote computer in PowerShell 1.0, so you need to use WMI's registry management class, StdRegProv, for this purpose. The StdRegProv class provides a useful set of methods that make reading the registry simple no matter whether you're reading the data from the local machine or a remote computer. (For more information about the StdRegProv class, see MSDN's StdRegProv Class web page.)