Private/Core/Get-InstalledApplication.ps1
|
function Get-InstalledApplication { <# .SYNOPSIS Gets installed applications from registry and winget .DESCRIPTION Retrieves installed application information using both registry detection and winget for comprehensive coverage .PARAMETER AppId Optional winget app ID to filter results .PARAMETER Name Optional application name pattern to filter results #> [CmdletBinding()] param( [Parameter()] [string]$AppId, [Parameter()] [string]$Name ) $results = @() # Try winget first if available if (Test-WingetAvailableInternal) { try { $wingetParams = @{} if ($AppId) { $wingetParams['Id'] = $AppId } $packages = Get-WinGetPackage @wingetParams -ErrorAction SilentlyContinue foreach ($pkg in $packages) { if ($Name -and $pkg.Name -notlike "*$Name*") { continue } $availVer = if ($pkg.AvailableVersions -and $pkg.AvailableVersions.Count -gt 0) { $pkg.AvailableVersions[0] } else { $null } $results += [PSCustomObject]@{ Source = 'Winget' AppId = $pkg.Id Name = $pkg.Name Version = $pkg.InstalledVersion AvailableVersion = $availVer UpdateAvailable = $pkg.IsUpdateAvailable Publisher = $pkg.Source } } } catch { Write-PatchLog "Winget query failed: $_" -Type Warning } } # Also check registry for apps not in winget $registryPaths = @( 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*' 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*' ) foreach ($regPath in $registryPaths) { try { $regApps = Get-ItemProperty -Path $regPath -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -and $_.DisplayVersion } foreach ($app in $regApps) { if ($Name -and $app.DisplayName -notlike "*$Name*") { continue } # Skip if already found via winget $existingWinget = $results | Where-Object { $_.Name -eq $app.DisplayName -or ($_.AppId -and $app.PSChildName -like "*$($_.AppId)*") } if ($existingWinget) { continue } $results += [PSCustomObject]@{ Source = 'Registry' AppId = $app.PSChildName Name = $app.DisplayName Version = $app.DisplayVersion AvailableVersion = $null UpdateAvailable = $false Publisher = $app.Publisher } } } catch { # Continue with other paths } } return $results } function Test-WingetAvailableInternal { <# .SYNOPSIS Internal check for winget availability #> [CmdletBinding()] param() try { $module = Get-Module -Name 'Microsoft.WinGet.Client' -ListAvailable -ErrorAction SilentlyContinue return ($null -ne $module) } catch { return $false } } |