A script to inventory the software installed on one or more computers. It will include both 32 bit and 64 bit software.
There are several registry locations where installed software is logged:
64 bit = HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\
32 bit = HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\
There are also equivalent locations for per-user software under HKCU, these are mainly used for things like Browser Plugins, Citrix applications and small utility programs, these are NOT scanned by the script below.
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\
HKCU\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\
<# .NOTES Name: Get-Programs.ps1 Author: Simon Sheppard, based on a script by Sitaram Pamarthi. Requires: PowerShell v2 or higher. Version: 1.01 23-June-2015 - Initial Release, with export to CSV. .SYNOPSIS List installed Programs on one or more computers. .DESCRIPTION This script retrieves the installed software directly from the registry it does not rely on having an SCCM client installed. .PARAMETER ComputerName The computer(s) to be checked, by default the local computer. .EXAMPLE Get-Programs.ps1 workstation64 .LINK https://windevcluster.com/ps/syntax-programs.html #> [cmdletbinding()] param( [parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [string[]]$ComputerName = $env:computername, [string]$OutputFile = "C:\batch\Installed_Programs.csv" ) BEGIN { $UninstallRegKey="SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall" Remove-Item $OutputFile -ErrorAction SilentlyContinue } PROCESS { function Get-InstalledApps { # This function will loop through the applications installed on one PC # and output one object for each Application with all its properties. # optionally saving/appending to a .CSV spreadsheet. ForEach ($App in $Applications) { $AppRegistryKey = $UninstallRegKey + "\\" + $App $AppDetails = $HKLM.OpenSubKey($AppRegistryKey) $AppGUID = $App $AppDisplayName = $($AppDetails.GetValue("DisplayName")) $AppVersion = $($AppDetails.GetValue("DisplayVersion")) $AppPublisher = $($AppDetails.GetValue("Publisher")) $AppInstalledDate = $($AppDetails.GetValue("InstallDate")) $AppUninstall = $($AppDetails.GetValue("UninstallString")) if(!$AppDisplayName) { continue } $OutputObj = New-Object -TypeName PSobject $OutputObj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $Computer.ToUpper() $OutputObj | Add-Member -MemberType NoteProperty -Name AppName -Value $AppDisplayName $OutputObj | Add-Member -MemberType NoteProperty -Name AppVersion -Value $AppVersion $OutputObj | Add-Member -MemberType NoteProperty -Name AppVendor -Value $AppPublisher $OutputObj | Add-Member -MemberType NoteProperty -Name InstalledDate -Value $AppInstalledDate $OutputObj | Add-Member -MemberType NoteProperty -Name UninstallKey -Value $AppUninstall $OutputObj | Add-Member -MemberType NoteProperty -Name AppGUID -Value $AppGUID if ($RegistryView -eq 'Registry32') { $OutputObj | Add-Member -MemberType NoteProperty -Name Arch -Value '32' } else { $OutputObj | Add-Member -MemberType NoteProperty -Name Arch -Value '64' } $OutputObj # Export to a file $OutputObj | Export-CSV -append -noTypeinformation -path $OutputFile } } foreach($Computer in $ComputerName) { Write-Output "Computer: $Computer" if(Test-Connection -ComputerName $Computer -Count 1 -ea 0) { # Get the architecture 32/64 bit $arch = (Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computer -ea 0).OSArchitecture if ($arch -eq '64-bit') { # If 64 bit check both 32 and 64 bit locations in the registry $RegistryViews = @('Registry32','Registry64') } else { # Otherwise only 32 bit $RegistryViews = @('Registry32') } ForEach ( $RegistryView in $RegistryViews ) { # Get the reg key(s) where add/remove program information is stored. $HKLM = [microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$computer,$RegistryView) $UninstallRef = $HKLM.OpenSubKey($UninstallRegKey) $Applications = $UninstallRef.GetSubKeyNames() # Now we have the registry locations, call the function which will enumerate # all the applications on this PC Get-InstalledApps } } } } end {}
For instructions of how to download and run this script see: Run a PowerShell script.
When running this script, provide a path for the Excel/CSV $OutputFile plus the computers to inventory.
The output will default to "C:\batch\Installed_Programs.csv"
The script returns, the Computer Name, Application Name, Vendor, Installation date, Uninstall key/command, GUID and Architecture (32 or 64 bit).
To access the registry of remote computers, the Remote Regsitry service needs to be running, the Remote Registry service can be enabled and started remotely using SC.exe
This script will only work for software installed using the standard Microsoft Windows Installer routines, while this approach covers most software there will always be a few packages which do things their own way. Commercial software inventory programs typically include the unique signatures and install locations for a large number of popular packages.
Get a list of all the programs installed on the computers: computer64 and computer65:
PS C:\> ./Get-Programs.ps1 computer64, computer65 -outputfile "C:\reports\software.csv"
Display help:
PS C:\> Get-Help ./Get-Programs.ps1
“Be less curious about people and more curious about ideas” ~ Maria Skłodowska-Curie
psp - PowerShell Ping.
function Get-Software - An inventory function that includes HKCU (per user installations).
Get installed software.ps1 - Guy Leech’s script which can list and also uninstall software.