Quick Links

If you're an IT admin, chances are high that you've had to install software for others. Endpoint management is big business these days, and maintaining software across hundreds or thousands of computers is common in large organizations. Big business usually means big $$, though.

What if you're in an organization with little-to-no budget? Maybe yourself or someone on your team has gotten into using PowerShell to automate various tasks? In that case, using PowerShell to manage software across many endpoints at once may be beneficial.

The PowerShell scripting language is a powerful flexible language that seems to handle just about anything in a Windows environment. Working with software on remote computers is a piece of cake!

In this article, you're going to learn how you can use PowerShell to build installed software reports. Although PowerShell is capable of installing software as well, you'll focus on querying software that's been installed via other means.

Where Software Is Registered

The term "software" is a vague term, especially on Windows. When a software package is installed, it's entirely up to the software developer to determine what changes on the user's computer. Software installers copy files, create registry keys, add WMI instances, and more. The key to building an accurate software inventory report, regardless of the method, is first understanding what to look for.

Although installed software is registered in WMI, a more reliable way to find this information is to use the registry.

Every modern version of Windows stores installed software information in the three registry keys below. Depending on how the software was installed, it always is stored as a registry key under one of these parent keys.

  • HKEY_LOCAL_MACHINE(32-bit path)
  • HKEY_LOCAL_MACHINE6432Node(64-bit path)
  • HKEY_CURRENT_USER(for every user profile)

Each child registry key in these parent keys is typically named for the software's globally unique identifier (GUID). Inside of that key, you can find registry values for software title, version, and more.

Remote PC Requirements

To use the code covered in this article, I'm assuming you have PowerShell Remoting enabled and available on your remote computers. You can test PowerShell Remoting by attempting to execute a simple command like 

        Invoke-Command -ComputerName REMOTEPCNAME -ScriptBlock {1}
    

. If this fails, the rest of the information covered in this article won't work either.

Using the PSSoftware Community Module

To prevent recreating the wheel and building your own PowerShell tool, let's use an existing one. I created a PowerShell module called PSSoftware a while back that solves this problem well.

First, in an administrative PowerShell console, download and install the PSSoftware PowerShell module from the PowerShell Gallery by running

        Install-Module PSSoftware
    

.

Once you have the module installed, inspect the commands available to you by running

        Get-Command -Module PSSoftware -Noun Software
    

. You'll see a few commands like

        Get-InstalledSoftware
    

,

        Install-Software
    

 ,and

        Remove-Software
    

. These commands are the main functions to manage software. In this article, I focus on the

        Get-InstalledSoftware
    

function.

Test out the

        Get-InstalledSoftware
    

command by first running it locally with no parameters. You immediately see many different software packages fly by.

        PS51> Get-InstalledSoftware

ModifyPath : MsiExec.exe /I{4CF4DB38-0692-4A5B-BCE8-1667C51E8416}
VersionMajor : 14
Version : 14.0.500.272
sEstimatedSize2 : 732
URLInfoAbout :
NoRepair : 1
InstallSource : C:ProgramDataPackage Cache{4CF4DB38-0692-4A5B-BCE8-1667C51E8416}v14.0.500.272x64
Contact :
Size :
InstallLocation :
VersionMinor : 0
SystemComponent : 1
EstimatedSize : 1464
URLUpdateInfo :
InstallDate : 20170716
Comments :
WindowsInstaller : 1
HelpLink : https://go.microsoft.com/fwlink/?LinkId=154582
UninstallString : MsiExec.exe /I{4CF4DB38-0692-4A5B-BCE8-1667C51E8416}
GUID : {4CF4DB38-0692-4A5B-BCE8-1667C51E8416}
HelpTelephone :
Readme : Placeholder for ARP readme in case of no UI
Publisher : Microsoft Corporation
Language : 1033
Name : SQL Server vNext CTP2.0 XEvent
AuthorizedCDFPrefix :
PSComputerName : MACWINVM
RunspaceId : da83572b-150b-43b6-923a-14e516a77ba3
--snip--

You can limit that output down to just the title and version using the Select-Object cmdlet.

        PS51> Get-InstalledSoftware | Select-Object -Property Name,Version
    

To query a remote computer, use the ComputerName parameter. The same software packages are returned.

Perhaps you'd rather not see all installed software but just software matching a specific title. You can filter this information using the Where-Object cmdlet. The following example finds all the software that starts with SQL on the remote computer.

        PS51> Get-InstalledSoftware | Where-Object {$_.Name -like 'SQL*'} | Select-Object -Property Name,Version
    

Summary

Once you understand where installed software is stored and can access it with PowerShell, the world is your oyster. From here, you can quickly expand this code to multiple computers, looking for numerous packages and more.

Using free community PowerShell modules is a great way to build software inventor reports on the cheap!