There are situations where you need to check whether you or your users have certain software installed, and what is its version. You may want to check if the software is up to date or if your GPO-deployed software has been installed for a certain user. I’ll show you several methods you can use to check that with PowerShell.
Quick navigation:
- Check installed software list locally
- Check installed software list remotely
- Check if GPO-deployed software was applied successfully
Check what’s installed on your computer
To check what software is installed, you can always use Programs and Features in your Control Panel or browse all disk partitions in search of a specific app. You can even try and find an app in the Start menu in order to launch it and search for its version number manually. However, the problem with those methods is that they are as far from “quick and automatic” as they can be. Checking the installed software versions by using PowerShell allows you to gather data that you need much quicker.
Get installed software list with Get-WmiObject
The first method is as simple as pasting a simple query:
Get-WmiObject -Class Win32_Product
You can also easily filter the data to find specific applications from a single vendor, together with their versions, for example:
Get-WmiObject -Class Win32_Product | where vendor -eq CodeTwo | select Name, Version
Despite being very easy, this method has a major downside – it takes quite a while to return the results.
Query registry for installed software
Another method of getting a list of installed software is querying the registry. The following short script returns the list of applications together with their versions:
$InstalledSoftware = Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall" foreach($obj in $InstalledSoftware){write-host $obj.GetValue('DisplayName') -NoNewline; write-host " - " -NoNewline; write-host $obj.GetValue('DisplayVersion')}
Now, take a quick look at the HKLM element bolded above. It means that the list of software returned by the script is all the software installed on the LM – local machine. However, applications can be installed per user as well. To return a list of applications of the currently logged user, change HKLM to HKCU (CU stands for “current user”):
$InstalledSoftware = Get-ChildItem "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall"
foreach($obj in $InstalledSoftware){write-host $obj.GetValue('DisplayName') -NoNewline; write-host " - " -NoNewline; write-host $obj.GetValue('DisplayVersion')}
Getting the list of recently installed software from the Event Log
If you want to check only the recently installed software, you can use the following cmdlet to search through the Event Log.
Get-WinEvent -ProviderName msiinstaller | where id -eq 1033 | select timecreated,message | FL *
This method of finding out installed software is most reliable for the recently added elements because, by default, event logs are set to overwrite the oldest records (circular logging).
Learn more about using PowerShell to check Windows Event Logs and filtering results
Get a list of installed software remotely
Each of the methods mentioned above can also be used to check software installed on other machines in the same network. If you create a list of all the computer names in your network, you can use the methods below within a Foreach loop to return results from more than a single remote PC.
$pcname in each script stands for the name of the remote computer on which you want to get a list of installed software and their versions.
Get installed software list with remote Get-WmiObject command
The following cmdlet is, again, the easiest in the bunch, but can take some time to finish:
Get-WmiObject Win32_Product -ComputerName $pcname | select Name,Version
where $pcname is the name of the computer you want to query.
Check installed software with remote registry query
Remote registry queries are slightly more complicated and require the Remote Registry service to be running. A sample query is as follows:
$list=@() $InstalledSoftwareKey="SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall" $InstalledSoftware=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$pcname) $RegistryKey=$InstalledSoftware.OpenSubKey($InstalledSoftwareKey) $SubKeys=$RegistryKey.GetSubKeyNames() Foreach ($key in $SubKeys){ $thisKey=$InstalledSoftwareKey+"\\"+$key $thisSubKey=$InstalledSoftware.OpenSubKey($thisKey) $obj = New-Object PSObject $obj | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $pcname $obj | Add-Member -MemberType NoteProperty -Name "DisplayName" -Value $($thisSubKey.GetValue("DisplayName")) $obj | Add-Member -MemberType NoteProperty -Name "DisplayVersion" -Value $($thisSubKey.GetValue("DisplayVersion")) $list += $obj } $list | where { $_.DisplayName } | select ComputerName, DisplayName, DisplayVersion | FT
Check recently installed software list from the Event Log remotely
Checking a user’s event log remotely requires adding a single attribute (-ComputerName) to the cmdlet used before:
Get-WinEvent -ComputerName $pcname -ProviderName msiinstaller | where id -eq 1033 | select timecreated,message | FL *
Check if a GPO-deployed software was applied successfully
If you applied a certain software version via GPO, you can easily check if this GPO was successfully applied to a user or not. All you need is the GPResult tool and names of the target computer and user:
gpresult /s "PCNAME" /USER "Username" /h "Target location of the HTML report"
Then, look for your GPO name and check if it is listed under Applied GPOs or Denied GPOs. The sample GPO below is in the Applied GPOs group.
Not sure if anyone can help? I use SCCM to deploy software across a college estate. Each month I manually check the most up to date version online and then update our content source if needed. Is there a way using poweshell/SCCM to notify me when an updated version of software is available?
I currently manually check each site once a month which can be time consuming. Thanks
Hi
I am running below script
$list=@()
$InstalledSoftwareKey=”SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall”
$InstalledSoftware=[microsoft.win32.registrykey]::OpenRemoteBaseKey(‘LocalMachine’,$pcname)
$RegistryKey=$InstalledSoftware.OpenSubKey($InstalledSoftwareKey)
$SubKeys=$RegistryKey.GetSubKeyNames()
Foreach ($key in $SubKeys){
$thisKey=$InstalledSoftwareKey+”\\”+$key
$thisSubKey=$InstalledSoftware.OpenSubKey($thisKey)
$obj = New-Object PSObject
$obj | Add-Member -MemberType NoteProperty -Name “ComputerName” -Value $pcname
$obj | Add-Member -MemberType NoteProperty -Name “DisplayName” -Value $($thisSubKey.GetValue(“DisplayName”))
$obj | Add-Member -MemberType NoteProperty -Name “DisplayVersion” -Value $($thisSubKey.GetValue(“DisplayVersion”))
$list += $obj
}
$list | where { $_.DisplayName -like “mozilla*”} | select ComputerName, DisplayName, DisplayVersion | FT
and i am getting expected result.
Can i ask your help on how to get same result from a list of PC in my office network? basically i want to provide a txt file with 50 PC names
Thanks Alex
hey Adam, how can I use this script when I need to check hundreds of remote pcs in a domain. Can I somehow use dns name pattern of our machines to get all pcs? Somehow like u explained with the -like “Mozilla*” command – can I filter for -like “DNSNAME*”
Hi,
I’m afraid you won’t be able to use the -like filter for this scenario. You could, however, get a list of all PCs to a CSV file, and then use a foreach loop to go through all the PCs, adding their names to the -ComputerName parameter.
Hi Adam,
We need help with this powershell command for installed software list. Is there any way we can run this for multiple servers by passing the value in a loop from a .txt or .csv file?
Get-WmiObject Win32_Product -ComputerName $pcname | select Name,Version
Sure you can. Just remember this cmdlet takes “forever” to finish for a single PC, even more when done remotely. For multiple remote PCs it will lag appropriately longer.
You could do something like that (the script assumes you have a CSV file with the ComputerName header:
$pcnames = Import-Csv -Path <Your CSV Path>
$pcnames = $pcnames.ComputerName
foreach ($pcname in $pcnames){
$pcname;
Get-WmiObject Win32_Product -ComputerName $pcname | select Name,Version
}
Many Thanks for this
If I need to use registry script for remote computer
and make it list specific software
for example list firefox and its version
How I can do that
This section explains how to do this. To display only specific software, you can modify the last line to, for example:
$list | where { $_.DisplayName -like "Mozilla*"} | select ComputerName, DisplayName, DisplayVersion | FT
hey even i need licenses of installed applications in win, did you find solution for it?
Hi, is there any way to then only get the value of an DisplayVersion?
So the output is only the version, without the additional DisplayVersion =”etcetc”. How to i get powershell to only put the “etcetc” in a string.
Thanks
I’m not sure I understand what you want to achieve. Do you mean this method? The method used in this script gets only the value of the DisplayVersion attribute.
How can we get details on what software was installed by other software? Example Visual Studios installs a ton of software besides Visual Studios. Sql Server similar. Is this possible?
Not really. You can sort results by installation date (to look for software installed in the same date as, for example, Visual Studio) or by vendor to point you into the right direction, but those filters might not be too accurate.
Do not use “Get-WmiObject -Class Win32_Product”
This initiates a app consistency check to determine the app is in good condition, and if it finds any issues with the app, it will initiate a repair install. Additionally it is a very slow query!
The more reliable option is to use Registry query for the “HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” (and the “HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall”)>
Quality post!
Can we get List of installed software along with associated license details from any of the command or any other commands?If You please help
What exactly do you mean by “license details”? Do you mean license keys? I’m afraid there is no easy way to fetch any licensing details using PowerShell – each vendor can have a different method of storing this kind of information.