function Get-Software { <# .SYNOPSIS Reads installed software from registry .PARAMETER DisplayName Name or part of name of the software you are looking for .EXAMPLE Get-Software -DisplayName *Office* returns all software with "Office" anywhere in its name .MORE INFO https://powershell.one/code/5.html #> param ( # emit only software that matches the value you submit: [string] $DisplayName = '*' ) #region define friendly texts: $Scopes = @{ HKLM = 'All Users' HKCU = 'Current User' } $Architectures = @{ $true = '32-Bit' $false = '64-Bit' } #endregion #region define calculated custom properties: # add the scope of the software based on whether the key is located # in HKLM: or HKCU: $Scope = @{ Name = 'Scope' Expression = { $Scopes[$_.PSDrive.Name] } } # add architecture (32- or 64-bit) based on whether the registry key # contains the parent key WOW6432Node: $Architecture = @{ Name = 'Architecture' Expression = {$Architectures[$_.PSParentPath -like '*\WOW6432Node\*']} } #endregion #region define the properties (registry values) we are after # define the registry values that you want to include into the result: $Values = 'AuthorizedCDFPrefix', 'Comments', 'Contact', 'DisplayName', 'DisplayVersion', 'EstimatedSize', 'HelpLink', 'HelpTelephone', 'InstallDate', 'InstallLocation', 'InstallSource', 'Language', 'ModifyPath', 'NoModify', 'PSChildName', 'PSDrive', 'PSParentPath', 'PSPath', 'PSProvider', 'Publisher', 'Readme', 'Size', 'SystemComponent', 'UninstallString', 'URLInfoAbout', 'URLUpdateInfo', 'Version', 'VersionMajor', 'VersionMinor', 'WindowsInstaller', 'Scope', 'Architecture' #endregion #region Define the VISIBLE properties # define the properties that should be visible by default # keep this below 5 to produce table output: [string[]]$visible = 'DisplayName','DisplayVersion','Scope','Architecture' [Management.Automation.PSMemberInfo[]]$visibleProperties = [System.Management.Automation.PSPropertySet]::new('DefaultDisplayPropertySet',$visible) #endregion #region read software from all four keys in Windows Registry: # read all four locations where software can be registered, and ignore non-existing keys: Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*', 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*', 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*', 'HKCU:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' -ErrorAction Ignore | # exclude items with no DisplayName: Where-Object DisplayName | # include only items that match the user filter: Where-Object { $_.DisplayName -like $DisplayName } | # add the two calculated properties defined earlier: Select-Object -Property *, $Scope, $Architecture | # create final objects with all properties we want: Select-Object -Property $values | # sort by name, then scope, then architecture: Sort-Object -Property DisplayName, Scope, Architecture | # add the property PSStandardMembers so PowerShell knows which properties to # display by default: Add-Member -MemberType MemberSet -Name PSStandardMembers -Value $visibleProperties -PassThru #endregion } Get-Software -DisplayName *Office*