Here is a fairly useful function that will return all installed software on your system as well as its publisher, install date and uninstall string. Uninstall strings are useful for automated and/or manual removal of software without any "uninstallers" or Windows' uninstall feature. All details of how it can be run and how you can pipe the function to other cmdlets are in its header. Updated on 11-03-19: - It now loads the HKEY_USERS hive and loops through the local registry for each account SID to further gather all locally installed software. - Values with no properties assigned to them will return as '<null>' - The software's package-specific GUID is also returned. - The object returned with all the software information is now automatically sorted by the Display Name of the software for easier navigation. Code: Function Get-InstalledSoftware { <# .SYNOPSIS Display detailed information about the currently installed software on a device. .DESCRIPTION Return detailed information about the software currently installed on the device. Performs a query loop through the system registry to gather roaming installed software. Loads the HKEY_USERS hive and performs a query loop through the registry to gather locally installed software for each account SID. The software information returned includes its version, publisher, installation date, GUID and uninstall string. The GUID and uninstall string allows for command-line configuration or uninstallation of software. Any properties that do not contain any information will return as '<null>'. .EXAMPLE PS C:\> Get-InstalledSoftware | Where-Object -Property DisplayName -Like SAPIEN* | Select-Object -Property DisplayName, UninstallString -Unique This one-line command uses the pipe-line to pipe the Get-InstalledSoftware results to the Where-Object cmdlet to filter out all software except SAPIEN software. The SAPIEN-specific software is then piped to the Select-Object cmdlet to only return the DisplayName and UninstallStrings of the installed software. The -Unique switch it used to prevent any duplicate entries from being displayed. PS C:\> SAPIEN Document Explorer 2019 msiexec.exe /x {FDD74C8F-E765-4EBE-A395-58CC7DB9AE15} AI_UNINSTALLER_CTP=1 PS C:\> SAPIEN PowerShell Studio 2019 msiexec.exe /x {A6A692FE-CDB1-4F93-AB53-DE6FDA13A003} AI_UNINSTALLER_CTP=1 PS C:\> SAPIEN Updates msiexec.exe /x {8E30326B-DCB2-4165-84B2-0725FB90DFAD} AI_UNINSTALLER_CTP=1 PS C:\> SAPIEN ScriptMerge 2019 msiexec.exe /x {C6F25D63-A5DE-4BE9-8111-56EAEEB41D40} AI_UNINSTALLER_CTP=1 .EXAMPLE PS C:\> Get-InstalledSoftware | Select-Object -ExpandProperty DisplayName | Out-File -FilePath "$HOME\Desktop\InstalledSoftware.txt" -Force This command will get all installed software on the device and output the DisplayNames to an InstalledSoftware.txt file on the Desktop. .OUTPUTS PSCustomObject .INPUTS None #> [CmdletBinding()] [OutputType([PSCustomObject])] Param () Begin { If (!(Test-Path -LiteralPath HKU:)) { $HKUDrive = New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS } } Process { $UninstallKeys = @('HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall') $UninstallKeys += Get-ChildItem -LiteralPath HKU: -ErrorAction SilentlyContinue | Where-Object -Property Name -Match 'S-\d-\d+-(\d+-){1,14}\d+$' | ForEach-Object -Process { "HKU:\$($_.PSChildName)\Software\Microsoft\Windows\CurrentVersion\Uninstall" } $UninstallKeys = $UninstallKeys | Get-ChildItem | ForEach-Object -Process { Get-ItemProperty -Path $_.PsPath } | ForEach-Object -Process { [PSCustomObject]@{ DisplayName = If ($_.DisplayName) { $_.DisplayName } Else { '<null>' }; DisplayVerison = If ($_.DisplayVersion) { $_.DisplayVersion } Else { '<null>' }; Publisher = If ($_.Publisher) { $_.Publisher } Else { '<null>' }; InstallDate = If ($_.InstallDate) { $_.InstallDate } Else { '<null>' }; GUID = If ($_.PSChildName -and $_.PSChildName -match '\b[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}\b') { $_.PSChildName } Else { '<null>' }; UninstallString = If ($_.UninstallString) { $_.UninstallString } Else { '<null>' } } } $UninstallKeys | Where-Object { $_.DisplayName -ne '<null>' -and $_.UninstallString -ne '<null>' } | Sort-Object -Property DisplayName } End { If ($HKUDrive) { Remove-PSDrive -Name $HKUDrive.Name } } }
Some empty registry keys exist on Win 7/8.1 (and probably 10) Spoiler Code: Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\AddressBook] [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Connection Manager] "SystemComponent"=dword:00000001 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\DirectDrawEx] [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\DXM_Runtime] [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Fontcore] [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\IE40] [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\IE4Data] [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\IE5BAKEX] [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\IEData] [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\MobileOptionPack] [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\MPlayer2] [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\SchedulingAgent] [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\WIC] "NoRemove"=dword:00000001 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}.KB2151757] @="KB2151757" [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}.KB2467173] @="KB2467173" [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}.KB2524860] @="KB2524860" [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}.KB2544655] @="KB2544655" [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}.KB2549743] @="KB2549743" [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}.KB2565063] @="KB2565063" [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}.KB2608539] @="KB2608539" [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}.KB2689322] @="KB2689322" [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}.KB2723430] @="KB2723430" [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}.KB2821701] @="KB2821701" [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}.KB2845370] @="KB2845370" [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}.KB2890375] @="KB2890375" [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}.KB982573] @="KB982573" the latest keys are pat of VC++ 2010 redist maybe it's best to verify them and exclude them Code: {if ($InstallProperty.DisplayName -ne $nul) { [PSCustomObject]@{ DisplayName = $InstallProperty.DisplayName DisplayVerison = $InstallProperty.DisplayVersion Publisher = $InstallProperty.Publisher InstallDate = $InstallProperty.InstallDate HelpLink = $InstallProperty.HelpLink UninstallString = $InstallProperty.UninstallString } } } additionally, x86 programs on x64 system have separate path Code: [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall] thanks
I added that additional registry path although I personally have never noticed a difference with it enabled (then again, I have virtually no x86 programs). I also added a small filter to output only objects that have a valid Display Name and no duplicate programs. One way or another, some programs will have $null values for some of the properties but by filtering out the Display Name, it prevents those objects with no values from displaying.
I updated this function: In addition to querying the system registry hives, it now loads the HKEY_USERS hive and loops through the local registry for each account SID to further gather all locally installed software. The software-specific GUID is now included. Added better formatting for the object returned with the software data.