functions/Get-WGInstalled.ps1
Function Get-WGInstalled { [cmdletbinding()] [OutputType("WGInstalled")] Param( [Parameter(Position = 0, HelpMessage = "Specify a winget source")] [ValidateNotNullOrEmpty()] [string]$Source = "winget" ) Begin { Write-Verbose "[$((Get-Date).TimeofDay) BEGIN ] Starting $($myinvocation.mycommand)" $tmpFile = "$env:temp\wgExport_{0}.json" -f (Get-Date -Format yyyymmdd) } #begin Process { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Building list of packages with a winget source" [void](winget export -s winget -o $tmpFile --include-versions) if (Test-Path -Path $tmpFile) { #import the json file Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Importing temporary JSON data" $json = Get-Content -Path $tmpFile | ConvertFrom-Json #get the packages $count = $json.Sources.packages.count Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Found $count packages. Getting details." $jobList = [system.collections.generic.list[object]]::new() foreach ($pkg in $json.Sources.packages) { Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] $($pkg.PackageIdentifier)" $i++ #9 August 2022 Using Threadjobs to get online package details for better scaling - JDH $sb = { Param([object]$pkg, [string]$source) Function _parseVersion { #parse out odd characters from version strings [cmdletbinding()] Param([string]$VersionString) if ($versionString -match "unknown") { $out = $null } elseif ($VersionString -match "[\<\>]") { $out = ($VersionString -replace $matches.values, "").Trim() } else { $out = $VersionString.Trim() } $out } try { $show = winget show --id $pkg.PackageIdentifier --source $source [regex]$rxname = "(?<=\w\s).*(?=\s\[[\S\.]+\])" $installed = _parseVersion $pkg.version $online = _parseVersion (($show | Select-String "Version:") -split "Version: ")[1].trim() @{ Name = $rxname.match($($show | Select-String "Found\s")).value ID = $pkg.PackageIdentifier InstalledVersion = $installed OnlineVersion = $online Publisher = $(Try { (($show | Select-String "Publisher:") -split "Publisher: ")[1].trim() } Catch { $null }) PublisherURL = $(Try { (($show | Select-String "Publisher Url:") -split "Publisher Url: ")[1].trim() } Catch { $null }) Author = $(Try { (($show | Select-String "Author:") -split "Author: ")[1].trim() } Catch { $null }) Moniker = $(Try { (($show | Select-String "Moniker:") -split "Moniker: ")[1].trim() } Catch {$null }) Description = $(Try { (($show | Select-String "Description:") -split "Description: ")[1].trim() } Catch { $null }) Homepage = $(Try { (($show | Select-String "Homepage:") -split "Homepage: ")[1].trim() } Catch { $null }) Source = $Source } #output hash } #Try catch { #$show | Out-String | Write-Host -fore red Write-Warning "There was an unknown problem with $($pkg.PackageIdentifier)" } } $joblist.add($(Start-ThreadJob -ScriptBlock $sb -ArgumentList $pkg, $source -Name wg)) } #foreach pkg #process jobs Write-Verbose "[$((Get-Date).TimeofDay) PROCESS] Getting thread job results" Do { $joblist.FindAll({ $args[0].state -eq 'Completed' }) | ForEach-Object { #convert the job output to a defined object $r = $_ | Receive-Job [pscustomobject]@{ PSTypeName = "WGInstalled" Name = $r.name ID = $r.id InstalledVersion = $r.InstalledVersion OnlineVersion = $r.OnlineVersion Publisher = $r.Publisher PublisherUrl = $r.PublisherURL Author = $r.Author Moniker = $r.Moniker Description = $r.Description Homepage = $r.Homepage Source = $r.Source Computername = $env:computername } #output object [void]$joblist.remove($_) } } Until ($jobList.count -eq 0) } else { Write-Warning "There was a problem getting a list of installed packages." } } #process End { if (Test-Path -Path $tmpFile) { #always remove the temp file Remove-Item $tmpFile -whatif:$false } if (Get-Job -Name wg) { #always remove the threadjob Remove-Job -Name wg -Force -whatif:$false } Write-Verbose "[$((Get-Date).TimeofDay) END ] Ending $($myinvocation.mycommand)" } #end } #close Get-WGInstalled Update-TypeData -TypeName WGInstalled -MemberType ScriptProperty -MemberName Update -Value { <# compare versions first at [version] type, then as a simple string comparison to determine if there is an upgrade available. #> $a = $null $z = $null if (([version]::tryparse($this.onlineversion, [ref]$a)) -AND ([version]::tryparse($this.installedversion, [ref]$z))) { $a -gt $z } elseif ($null -eq $this.InstalledVersion) { $False } else { $this.installedversion -ne $This.onlineversion } } -Force |