Public/Get-vlInstalledApplication.ps1
Function Get-vlInstalledApplication { <# .SYNOPSIS Retrieves a list of all software installed on a Windows computer. .EXAMPLE PS C:\> Get-vlInstalledApplication This example retrieves all software installed on the local computer. .EXAMPLE PS C:\> (Get-vlInstalledApplication -Computer PC1 -Name 'Google Chrome').UninstallString Returns only the uninstall string of Google Chrome from PC1 .PARAMETER Computer If querying a remote computer, use the computer name here. .PARAMETER Name The software title you'd like to limit the query to. Does a '-match' comparison. .PARAMETER Guid The software GUID you'd like to limit the query to. .PARAMETER SilentUninstallerAvailable Limit the output to software with a silent uninstall string available. .NOTES Based on https://adamtheautomator.com/powershell-get-installed-software/ Author: vast limits GmbH #> [OutputType([System.Management.Automation.PSObject])] [CmdletBinding()] param ( [Parameter()] [ValidateNotNullOrEmpty()] [System.String]$Computer = $env:COMPUTERNAME, [Parameter(Mandatory = $false)] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential, [Parameter()] [ValidateNotNullOrEmpty()] [System.String]$Name, [Parameter()] [guid]$Guid, [Parameter()] [switch]$SilentUninstallerAvailable ) begin { } process { try { $scriptBlock = { If ($args[0].ContainsKey('Verbose')) { $VerbosePreference = 'Continue' } $args[0].GetEnumerator() | ForEach-Object { New-Variable -Name $_.Key -Value $_.Value } $UninstallKeys = @( "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall", "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" ) New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null $UninstallKeys += Get-ChildItem HKU: | Where-Object { $_.Name -match 'S-\d-\d+-(\d+-){1,14}\d+$' } | ForEach-Object { "HKU:\$($_.PSChildName)\Software\Microsoft\Windows\CurrentVersion\Uninstall" } if (-not $UninstallKeys) { Write-Warning -Message 'No software registry keys found' } else { foreach ($UninstallKey in $UninstallKeys) { $friendlyNames = @{ 'DisplayName' = 'Name' 'DisplayVersion' = 'Version' } Write-Verbose -Message "Checking uninstall key [$($UninstallKey)]" if ($Name) { $WhereBlock = { $_.GetValue('DisplayName') -match "$Name" } } elseif ($GUID) { $WhereBlock = { $_.PsChildName -eq $Guid.Guid } } else { $WhereBlock = { $_.GetValue('DisplayName') } } Write-Verbose "where block = $WhereBlock" if ($SilentUninstallerAvailable.IsPresent) { $WhereBlock2 = { ($_.GetValue('UninstallString') -match 'msiexec.exe') -OR ($_.GetValue('QuietUninstallString')) } $SwKeys = Get-ChildItem -Path $UninstallKey -ErrorAction SilentlyContinue | Where-Object $WhereBlock | Where-Object $WhereBlock2 } else { $SwKeys = Get-ChildItem -Path $UninstallKey -ErrorAction SilentlyContinue | Where-Object $WhereBlock } if (-not $SwKeys) { Write-Verbose -Message "No software keys in uninstall key $UninstallKey" } else { foreach ($SwKey in $SwKeys) { $output = @{ } foreach ($ValName in $SwKey.GetValueNames()) { if ($ValName -ne 'Version') { $output.InstallLocation = '' if ($ValName -eq 'InstallLocation' -and ($SwKey.GetValue($ValName)) -and (@('C:', 'C:\Windows', 'C:\Windows\System32', 'C:\Windows\SysWOW64') -notcontains $SwKey.GetValue($ValName).TrimEnd('\'))) { $output.InstallLocation = $SwKey.GetValue($ValName).TrimEnd('\') } [string]$ValData = $SwKey.GetValue($ValName) if ($friendlyNames[$ValName]) { $output[$friendlyNames[$ValName]] = $ValData.Trim() # Some registry values have trailing spaces. } else { $output[$ValName] = $ValData.Trim() # Some registry values trailing spaces } } } $output.GUID = '' if ($SwKey.PSChildName -match '\b[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}\b') { $output.GUID = $SwKey.PSChildName } If ($output.QuietUninstallString) { $output.UninstallString = $output.QuietUninstallString # if this is not a msiexec uninstall than make sure that we only get back silent uninstall strings $output.QuietUninstallString = $output.QuietUninstallString -replace '"', '`"' # escape quotation marks so that 'Uninstall-vlApplication' can handle pipeline input correctly #$output.QuietUninstallString = '"' + $output.QuietUninstallString + '"' } $output.UninstallString = $output.UninstallString -replace '"', '`"' # escape quotation marks so that 'Uninstall-vlApplication' can handle pipeline input correctly #$output.UninstallString = '"' + $output.UninstallString + '"' New-Object -TypeName PSObject -Prop $output } } } } } if ($Computer -eq $env:COMPUTERNAME) { Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $PSBoundParameters -Verbose:$VerbosePreference } else { Invoke-Command -ComputerName $Computer -ScriptBlock $scriptBlock -ArgumentList $PSBoundParameters -Credential $Credential -Verbose:$VerbosePreference } } catch { Write-Error -Message "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" } } } |