mirror of
https://github.com/rbalsleyMSFT/FFU.git
synced 2026-06-14 02:09:35 -06:00
Improves Winget search performance and user feedback
Refactors the Winget search functionality to enhance performance and provide a better user experience. - Updates the UI to show a wait cursor, disable the search button, and display a status message during the search operation. - Improves the post-search status message to differentiate between new and total applications found. - Utilizes `ForEach-Object -Parallel` to speed up the processing of search results on multi-core systems.
This commit is contained in:
@@ -11,10 +11,15 @@ function Search-WingetApps {
|
|||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[psobject]$State
|
[psobject]$State
|
||||||
)
|
)
|
||||||
try {
|
|
||||||
$searchQuery = $State.Controls.txtWingetSearch.Text
|
|
||||||
if ([string]::IsNullOrWhiteSpace($searchQuery)) { return }
|
|
||||||
|
|
||||||
|
$searchQuery = $State.Controls.txtWingetSearch.Text
|
||||||
|
if ([string]::IsNullOrWhiteSpace($searchQuery)) { return }
|
||||||
|
|
||||||
|
$State.Controls.txtStatus.Text = "Searching Winget for apps matching query '$searchQuery'..."
|
||||||
|
$State.Window.Cursor = [System.Windows.Input.Cursors]::Wait
|
||||||
|
$State.Controls.btnWingetSearch.IsEnabled = $false
|
||||||
|
|
||||||
|
try {
|
||||||
# Get current items from the ListView
|
# Get current items from the ListView
|
||||||
$currentItemsInListView = @()
|
$currentItemsInListView = @()
|
||||||
if ($null -ne $State.Controls.lstWingetResults.ItemsSource) {
|
if ($null -ne $State.Controls.lstWingetResults.ItemsSource) {
|
||||||
@@ -33,8 +38,6 @@ function Search-WingetApps {
|
|||||||
# Search for new apps, which are streamed directly as PSCustomObjects
|
# Search for new apps, which are streamed directly as PSCustomObjects
|
||||||
# with the required properties for performance.
|
# with the required properties for performance.
|
||||||
$searchedAppResults = Search-WingetPackagesPublic -Query $searchQuery -DefaultArchitecture $defaultArch
|
$searchedAppResults = Search-WingetPackagesPublic -Query $searchQuery -DefaultArchitecture $defaultArch
|
||||||
WriteLog "Found $($searchedAppResults.Count) apps matching query '$searchQuery'."
|
|
||||||
|
|
||||||
$finalAppList = [System.Collections.Generic.List[object]]::new()
|
$finalAppList = [System.Collections.Generic.List[object]]::new()
|
||||||
$addedAppIds = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase)
|
$addedAppIds = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase)
|
||||||
|
|
||||||
@@ -45,18 +48,37 @@ function Search-WingetApps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Add new search results, avoiding duplicates of already added (selected) apps
|
# Add new search results, avoiding duplicates of already added (selected) apps
|
||||||
|
$newAppsAddedCount = 0
|
||||||
foreach ($result in $searchedAppResults) {
|
foreach ($result in $searchedAppResults) {
|
||||||
if (-not $addedAppIds.Contains($result.Id)) {
|
# HashSet.Add returns $true if the item was added, $false if it already existed.
|
||||||
|
if ($addedAppIds.Add($result.Id)) {
|
||||||
$finalAppList.Add($result)
|
$finalAppList.Add($result)
|
||||||
$addedAppIds.Add($result.Id) | Out-Null # Track added IDs to prevent duplicates from search results themselves
|
$newAppsAddedCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Update the ListView's ItemsSource using the passed-in State object
|
# Update the ListView's ItemsSource using the passed-in State object
|
||||||
$State.Controls.lstWingetResults.ItemsSource = $finalAppList.ToArray()
|
$State.Controls.lstWingetResults.ItemsSource = $finalAppList.ToArray()
|
||||||
|
|
||||||
|
# Update status text
|
||||||
|
$statusText = ""
|
||||||
|
if ($newAppsAddedCount -gt 0) {
|
||||||
|
$statusText = "Found $newAppsAddedCount new applications. "
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$statusText = "No new applications found. "
|
||||||
|
}
|
||||||
|
$statusText += "Displaying $($finalAppList.Count) total applications."
|
||||||
|
$State.Controls.txtStatus.Text = $statusText
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
[System.Windows.MessageBox]::Show("Error searching for apps: $_", "Error", "OK", "Error")
|
$errorMessage = "Error searching for apps: $($_.Exception.Message)"
|
||||||
|
$State.Controls.txtStatus.Text = $errorMessage
|
||||||
|
[System.Windows.MessageBox]::Show($errorMessage, "Error", "OK", "Error")
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$State.Window.Cursor = $null
|
||||||
|
$State.Controls.btnWingetSearch.IsEnabled = $true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,18 +182,24 @@ function Search-WingetPackagesPublic {
|
|||||||
|
|
||||||
WriteLog "Searching Winget packages with query: '$Query'"
|
WriteLog "Searching Winget packages with query: '$Query'"
|
||||||
try {
|
try {
|
||||||
# Stream results directly from Find-WinGetPackage and convert them to simple PSCustomObjects
|
# Using ForEach-Object -Parallel can speed up object creation on multi-core systems
|
||||||
# on the fly using Select-Object with calculated properties. This is significantly faster
|
# by distributing the work across multiple threads.
|
||||||
# for large datasets as it avoids holding complex objects in memory and bypasses the
|
$results = Find-WinGetPackage -Query $Query -ErrorAction Stop
|
||||||
# expensive formatting system for the raw results.
|
WriteLog "Found $($results.Count) packages matching query '$Query'."
|
||||||
Find-WinGetPackage -Query $Query -ErrorAction Stop |
|
WriteLog "Creating output objects for Winget search results, please wait..."
|
||||||
Select-Object -Property @{Name = 'IsSelected'; Expression = { $false } },
|
$output = $results | ForEach-Object -Parallel {
|
||||||
Name,
|
[PSCustomObject]@{
|
||||||
Id,
|
IsSelected = [bool]$false
|
||||||
Version,
|
Name = [string]$_.Name
|
||||||
Source,
|
Id = [string]$_.Id
|
||||||
@{Name = 'Architecture'; Expression = { $DefaultArchitecture } },
|
Version = [string]$_.Version
|
||||||
@{Name = 'DownloadStatus'; Expression = { '' } }
|
Source = [string]$_.Source
|
||||||
|
Architecture = [string]$using:DefaultArchitecture
|
||||||
|
DownloadStatus = [string]::Empty
|
||||||
|
}
|
||||||
|
} -ThrottleLimit 20
|
||||||
|
WriteLog "Winget search completed. Created $($output.Count) output objects."
|
||||||
|
return $output
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
WriteLog "Error during Winget search: $($_.Exception.Message)"
|
WriteLog "Error during Winget search: $($_.Exception.Message)"
|
||||||
|
|||||||
Reference in New Issue
Block a user