Add Winget search panel with results list and save/import functionality

This commit is contained in:
rbalsleyMSFT
2025-02-17 18:05:22 -08:00
parent 81b3be894e
commit 02835579c1
2 changed files with 409 additions and 152 deletions
+352 -147
View File
@@ -7,7 +7,6 @@ param()
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
$FFUDevelopmentPath = $PSScriptRoot $FFUDevelopmentPath = $PSScriptRoot
$AppsPath = Join-Path $FFUDevelopmentPath "Apps" $AppsPath = Join-Path $FFUDevelopmentPath "Apps"
$OfficePath = Join-Path $AppsPath "Office"
# Add the new function for USB drive detection # Add the new function for USB drive detection
function Get-USBDrives { function Get-USBDrives {
@@ -204,7 +203,6 @@ function Confirm-WinGetInstallation {
# Some default values # Some default values
$defaultISOPath = "" $defaultISOPath = ""
$defaultWindowsRelease = 11 # numeric
$defaultWindowsArch = "x64" $defaultWindowsArch = "x64"
$defaultWindowsLang = "en-us" $defaultWindowsLang = "en-us"
$defaultWindowsSKU = "Pro" $defaultWindowsSKU = "Pro"
@@ -279,156 +277,81 @@ $windowsVersionMap = @{
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Clean up the Get-UIConfig function to remove duplicates and fix USBDriveList
function Get-UIConfig { function Get-UIConfig {
# --- Build Tab Values --- # Create hash to store configuration
$ffuDevPath = $window.FindName('txtFFUDevPath').Text
$customFFUNameTemplate = $window.FindName('txtCustomFFUNameTemplate').Text
$ffuCaptureLocation = $window.FindName('txtFFUCaptureLocation').Text
$shareName = $window.FindName('txtShareName').Text
$username = $window.FindName('txtUsername').Text
# General Build Options (Build tab WrapPanel)
$buildUSB = $window.FindName('chkBuildUSBDriveEnable').IsChecked
$compactOS = $window.FindName('chkCompactOS').IsChecked
$optimize = $window.FindName('chkOptimize').IsChecked
$allowVHDXCaching = $window.FindName('chkAllowVHDXCaching').IsChecked
$createCapture = $window.FindName('chkCreateCaptureMedia').IsChecked
$createDeployMedia = $window.FindName('chkCreateDeploymentMedia').IsChecked
# Build USB Drive Section (new)
$promptExt = $window.FindName('chkPromptExternalHardDiskMedia').IsChecked
$allowExt = $window.FindName('chkAllowExternalHardDiskMedia').IsChecked
# USB Drive Modification group (Build tab right column in new section)
$copyAutopilot = $window.FindName('chkCopyAutopilot').IsChecked
$copyUnattend = $window.FindName('chkCopyUnattend').IsChecked
$copyPPKG = $window.FindName('chkCopyPPKG').IsChecked
# --- Hyper-V Settings (from Hyper-V tab) ---
$cmbVMSwitch = $window.FindName('cmbVMSwitchName')
$vmSwitchName = $cmbVMSwitch.SelectedItem
if ($vmSwitchName -eq 'Other') { $vmSwitchName = $window.FindName('txtCustomVMSwitchName').Text }
$vmHostIPAddress = $window.FindName('txtVMHostIPAddress').Text
[int64]$diskSizeInGB = [int64]$window.FindName('txtDiskSize').Text
$diskSize = $diskSizeInGB * 1GB
[int64]$memoryInGB = [int64]$window.FindName('txtMemory').Text
$memory = $memoryInGB * 1GB
[int]$processors = [int]$window.FindName('txtProcessors').Text
$vmLocation = $window.FindName('txtVMLocation').Text
$logicalSectorObj = $window.FindName('cmbLogicalSectorSize').SelectedItem
$logicalSectorSize = [int]$logicalSectorObj.Content
# <-- NEW: retrieve FFUPrefix from the new textbox (VM Name Prefix)
$ffuPrefix = $window.FindName('txtVMNamePrefix').Text
# --- Windows Settings tab ---
$wrItem = $window.FindName('cmbWindowsRelease').SelectedItem
$windowsRelease = if ($wrItem -and $wrItem.Value) { [int]$wrItem.Value } else { 10 }
$windowsVersion = $window.FindName('cmbWindowsVersion').SelectedItem
$windowsArch = $window.FindName('cmbWindowsArch').SelectedItem
$windowsLang = $window.FindName('cmbWindowsLang').SelectedItem
$windowsSKU = $window.FindName('cmbWindowsSKU').SelectedItem
$mediaType = $window.FindName('cmbMediaType').SelectedItem
$productKey = $window.FindName('txtProductKey').Text
$isoPath = $window.FindName('txtISOPath').Text
# --- M365 Apps/Office tab ---
$installOffice = $window.FindName('chkInstallOffice').IsChecked
$officePath = $window.FindName('txtOfficePath').Text
$copyOfficeConfig = $window.FindName('chkCopyOfficeConfigXML').IsChecked
$officeConfigXMLFile = $window.FindName('txtOfficeConfigXMLFilePath').Text
# --- Drivers tab ---
$installDrivers = $window.FindName('chkInstallDrivers').IsChecked
$copyDrivers = $window.FindName('chkCopyDrivers').IsChecked
$downloadDrivers = $window.FindName('chkDownloadDrivers').IsChecked
$make = $window.FindName('cmbMake').SelectedItem
$model = $window.FindName('cmbModel').Text
$driversFolder = $window.FindName('txtDriversFolder').Text
$peDriversFolder = $window.FindName('txtPEDriversFolder').Text
$copyPEDrivers = $window.FindName('chkCopyPEDrivers').IsChecked
# --- Updates tab ---
$updateLatestCU = $window.FindName('chkUpdateLatestCU').IsChecked
$updateLatestNet = $window.FindName('chkUpdateLatestNet').IsChecked
$updateLatestDefender = $window.FindName('chkUpdateLatestDefender').IsChecked
$updateEdge = $window.FindName('chkUpdateEdge').IsChecked
$updateOneDrive = $window.FindName('chkUpdateOneDrive').IsChecked
$updateLatestMSRT = $window.FindName('chkUpdateLatestMSRT').IsChecked
$updatePreviewCU = $window.FindName('chkUpdatePreviewCU').IsChecked
# --- Applications tab ---
$installApps = $window.FindName('chkInstallApps').IsChecked
$installWingetApps = $window.FindName('chkInstallWingetApps').IsChecked
# Add USB drive selection to config
$selectedUSBDrives = @{}
$window.FindName('lstUSBDrives').Items | Where-Object { $_.IsSelected } | ForEach-Object {
$selectedUSBDrives[$_.Model] = $_.SerialNumber
}
# Build configuration hashtable (unsorted)
$config = [ordered]@{ $config = [ordered]@{
AllowExternalHardDiskMedia = $allowExt AllowExternalHardDiskMedia = $window.FindName('chkAllowExternalHardDiskMedia').IsChecked
AllowVHDXCaching = $allowVHDXCaching AllowVHDXCaching = $window.FindName('chkAllowVHDXCaching').IsChecked
BuildUSBDrive = $buildUSB BuildUSBDrive = $window.FindName('chkBuildUSBDriveEnable').IsChecked
CompactOS = $compactOS
CopyAutopilot = $copyAutopilot
CopyOfficeConfigXML = $copyOfficeConfig
CopyPEDrivers = $copyPEDrivers
CopyPPKG = $copyPPKG
CopyUnattend = $copyUnattend
CreateCaptureMedia = $createCapture
CreateDeploymentMedia = $createDeployMedia
CleanupAppsISO = $window.FindName('chkCleanupAppsISO').IsChecked CleanupAppsISO = $window.FindName('chkCleanupAppsISO').IsChecked
CleanupCaptureISO = $window.FindName('chkCleanupCaptureISO').IsChecked CleanupCaptureISO = $window.FindName('chkCleanupCaptureISO').IsChecked
CleanupDeployISO = $window.FindName('chkCleanupDeployISO').IsChecked CleanupDeployISO = $window.FindName('chkCleanupDeployISO').IsChecked
CleanupDrivers = $window.FindName('chkCleanupDrivers').IsChecked CleanupDrivers = $window.FindName('chkCleanupDrivers').IsChecked
Disksize = $diskSize CompactOS = $window.FindName('chkCompactOS').IsChecked
DownloadDrivers = $downloadDrivers CopyAutopilot = $window.FindName('chkCopyAutopilot').IsChecked
PromptExternalHardDiskMedia = $promptExt CopyDrivers = $window.FindName('chkCopyDrivers').IsChecked
FFUCaptureLocation = $ffuCaptureLocation CopyOfficeConfigXML = $window.FindName('chkCopyOfficeConfigXML').IsChecked
FFUDevelopmentPath = $ffuDevPath CopyPEDrivers = $window.FindName('chkCopyPEDrivers').IsChecked
ISOPath = $isoPath # <-- NEW: Add Windows ISO Path to config CopyPPKG = $window.FindName('chkCopyPPKG').IsChecked
MediaType = $mediaType CopyUnattend = $window.FindName('chkCopyUnattend').IsChecked
Make = $make CreateCaptureMedia = $window.FindName('chkCreateCaptureMedia').IsChecked
Model = $model CreateDeploymentMedia = $window.FindName('chkCreateDeploymentMedia').IsChecked
OfficeConfigXMLFile = $officeConfigXMLFile CustomFFUNameTemplate = $window.FindName('txtCustomFFUNameTemplate').Text
OfficePath = $officePath DiskSize = [int64]$window.FindName('txtDiskSize').Text * 1GB
OptionalFeatures = $window.FindName('txtOptionalFeatures').Text DownloadDrivers = $window.FindName('chkDownloadDrivers').IsChecked
PEDriversFolder = $peDriversFolder DriversFolder = $window.FindName('txtDriversFolder').Text
ProductKey = $productKey FFUCaptureLocation = $window.FindName('txtFFUCaptureLocation').Text
Processors = $processors FFUDevelopmentPath = $window.FindName('txtFFUDevPath').Text
FFUPrefix = $window.FindName('txtVMNamePrefix').Text
InstallApps = $window.FindName('chkInstallApps').IsChecked
InstallDrivers = $window.FindName('chkInstallDrivers').IsChecked
InstallOffice = $window.FindName('chkInstallOffice').IsChecked
InstallWingetApps = $window.FindName('chkInstallWingetApps').IsChecked
ISOPath = $window.FindName('txtISOPath').Text
LogicalSectorSizeBytes = [int]$window.FindName('cmbLogicalSectorSize').SelectedItem.Content
Make = $window.FindName('cmbMake').SelectedItem
MediaType = $window.FindName('cmbMediaType').SelectedItem
Memory = [int64]$window.FindName('txtMemory').Text * 1GB
Model = $window.FindName('cmbModel').Text
OfficeConfigXMLFile = $window.FindName('txtOfficeConfigXMLFilePath').Text
OfficePath = $window.FindName('txtOfficePath').Text
Optimize = $window.FindName('chkOptimize').IsChecked
PEDriversFolder = $window.FindName('txtPEDriversFolder').Text
ProductKey = $window.FindName('txtProductKey').Text
PromptExternalHardDiskMedia = $window.FindName('chkPromptExternalHardDiskMedia').IsChecked
Processors = [int]$window.FindName('txtProcessors').Text
RemoveFFU = $window.FindName('chkRemoveFFU').IsChecked RemoveFFU = $window.FindName('chkRemoveFFU').IsChecked
UpdateEdge = $updateEdge ShareName = $window.FindName('txtShareName').Text
UpdateLatestCU = $updateLatestCU UpdateEdge = $window.FindName('chkUpdateEdge').IsChecked
UpdateLatestDefender = $updateLatestDefender UpdateLatestCU = $window.FindName('chkUpdateLatestCU').IsChecked
UpdateLatestMSRT = $updateLatestMSRT UpdateLatestDefender = $window.FindName('chkUpdateLatestDefender').IsChecked
UpdateLatestNet = $updateLatestNet UpdateLatestMSRT = $window.FindName('chkUpdateLatestMSRT').IsChecked
UpdateOneDrive = $updateOneDrive UpdateLatestNet = $window.FindName('chkUpdateLatestNet').IsChecked
UpdatePreviewCU = $updatePreviewCU UpdateOneDrive = $window.FindName('chkUpdateOneDrive').IsChecked
VMHostIPAddress = $vmHostIPAddress UpdatePreviewCU = $window.FindName('chkUpdatePreviewCU').IsChecked
VMLocation = $vmLocation USBDriveList = @{}
VMSwitchName = $vmSwitchName Username = $window.FindName('txtUsername').Text
LogicalSectorSizeBytes = $logicalSectorSize VMHostIPAddress = $window.FindName('txtVMHostIPAddress').Text
Memory = $memory VMLocation = $window.FindName('txtVMLocation').Text
WindowsArch = $windowsArch VMSwitchName = if ($window.FindName('cmbVMSwitchName').SelectedItem -eq 'Other') {
WindowsLang = $windowsLang $window.FindName('txtCustomVMSwitchName').Text
WindowsRelease = $windowsRelease } else {
WindowsSKU = $windowsSKU $window.FindName('cmbVMSwitchName').SelectedItem
WindowsVersion = $windowsVersion }
FFUPrefix = $ffuPrefix # <-- new option for VM Name Prefix WindowsArch = $window.FindName('cmbWindowsArch').SelectedItem
USBDriveList = $selectedUSBDrives # Add USB drive selection WindowsLang = $window.FindName('cmbWindowsLang').SelectedItem
InstallApps = $installApps WindowsRelease = [int]$window.FindName('cmbWindowsRelease').SelectedItem.Value
InstallWingetApps = $installWingetApps WindowsSKU = $window.FindName('cmbWindowsSKU').SelectedItem
WindowsVersion = $window.FindName('cmbWindowsVersion').SelectedItem
} }
# Sort the configuration hashtable alphabetically by key # Add selected USB drives to the config
$sortedConfig = [ordered]@{} $window.FindName('lstUSBDrives').Items | Where-Object { $_.IsSelected } | ForEach-Object {
foreach ($key in ($config.Keys | Sort-Object)) { $config.USBDriveList[$_.Model] = $_.SerialNumber
$sortedConfig[$key] = $config[$key]
} }
return $sortedConfig
return $config
} }
function UpdateWindowsReleaseList { function UpdateWindowsReleaseList {
@@ -599,6 +522,84 @@ $script:versionData | Add-Member -MemberType ScriptMethod -Name NotifyPropertyCh
$script:versionData | Add-Member -MemberType NoteProperty -Name PropertyChanged -Value $null $script:versionData | Add-Member -MemberType NoteProperty -Name PropertyChanged -Value $null
$script:versionData | Add-Member -TypeName "System.ComponentModel.INotifyPropertyChanged" $script:versionData | Add-Member -TypeName "System.ComponentModel.INotifyPropertyChanged"
# Add a function to create a sortable list view for Winget search results
function Add-SortableColumn {
param(
[System.Windows.Controls.GridView]$gridView,
[string]$header,
[string]$binding,
[int]$width = 'Auto',
[bool]$isCheckbox = $false
)
$column = New-Object System.Windows.Controls.GridViewColumn
if ($isCheckbox) {
$template = New-Object System.Windows.FrameworkElementFactory([System.Windows.Controls.CheckBox])
$template.SetBinding([System.Windows.Controls.CheckBox]::IsCheckedProperty, (New-Object System.Windows.Data.Binding("IsSelected")))
$column.CellTemplate = New-Object System.Windows.DataTemplate
$column.CellTemplate.VisualTree = $template
}
else {
$column.DisplayMemberBinding = New-Object System.Windows.Data.Binding($binding)
}
# Create the header with sorting support
$columnHeader = New-Object System.Windows.Controls.GridViewColumnHeader
$columnHeader.Content = $header
$columnHeader.Tag = $binding
$column.Header = $columnHeader
if ($width -ne 'Auto') {
$column.Width = $width
}
$gridView.Columns.Add($column)
}
# Initialize tracking variables for sorting
$script:lastSortProperty = $null
$script:lastSortAscending = $true
# Function to sort ListView items
function Invoke-ListViewSort {
param(
[System.Windows.Controls.ListView]$listView,
[string]$property
)
# Toggle sort direction if clicking the same column
if ($script:lastSortProperty -eq $property) {
$script:lastSortAscending = -not $script:lastSortAscending
} else {
$script:lastSortAscending = $true
}
$script:lastSortProperty = $property
# Convert ListView items to array and split into selected and unselected
$items = @($listView.Items)
$selectedItems = @($items | Where-Object { $_.IsSelected })
$unselectedItems = @($items | Where-Object { -not $_.IsSelected })
# Sort unselected items
$sortedUnselected = if ($script:lastSortAscending) {
@($unselectedItems | Sort-Object -Property $property)
} else {
@($unselectedUnselected | Sort-Object -Property $property -Descending)
}
# Clear and repopulate ListView
$listView.Items.Clear()
# Add items back in correct order (selected first, then sorted unselected)
foreach ($item in $selectedItems) {
$listView.Items.Add($item)
}
foreach ($item in $sortedUnselected) {
$listView.Items.Add($item)
}
}
# Fix event handler parameter names to avoid $eventArgs conflicts
$window.Add_Loaded({ $window.Add_Loaded({
$script:cmbWindowsRelease = $window.FindName('cmbWindowsRelease') $script:cmbWindowsRelease = $window.FindName('cmbWindowsRelease')
$script:cmbWindowsVersion = $window.FindName('cmbWindowsVersion') $script:cmbWindowsVersion = $window.FindName('cmbWindowsVersion')
@@ -843,8 +844,8 @@ $window.Add_Loaded({
# Add keyboard handler # Add keyboard handler
$script:lstUSBDrives.Add_KeyDown({ $script:lstUSBDrives.Add_KeyDown({
param($sender, $e) param($eventSrc, $keyEvent)
if ($e.Key -eq 'Space') { if ($keyEvent.Key -eq 'Space') {
$selectedItem = $script:lstUSBDrives.SelectedItem $selectedItem = $script:lstUSBDrives.SelectedItem
if ($selectedItem) { if ($selectedItem) {
$selectedItem.IsSelected = !$selectedItem.IsSelected $selectedItem.IsSelected = !$selectedItem.IsSelected
@@ -858,7 +859,7 @@ $window.Add_Loaded({
# Add selection change handler # Add selection change handler
$script:lstUSBDrives.Add_SelectionChanged({ $script:lstUSBDrives.Add_SelectionChanged({
param($sender, $e) param($eventSrc, $selChangeEvent)
# Update Select All checkbox state # Update Select All checkbox state
$allSelected = -not ($script:lstUSBDrives.Items | Where-Object { -not $_.IsSelected }) $allSelected = -not ($script:lstUSBDrives.Items | Where-Object { -not $_.IsSelected })
$script:chkSelectAllUSBDrives.IsChecked = $allSelected $script:chkSelectAllUSBDrives.IsChecked = $allSelected
@@ -936,8 +937,14 @@ $window.Add_Loaded({
}) })
# Show/Hide Winget panel based on checkbox state # Show/Hide Winget panel based on checkbox state
$script:chkInstallWingetApps.Add_Checked({ $script:wingetPanel.Visibility = 'Visible' }) $script:chkInstallWingetApps.Add_Checked({
$script:chkInstallWingetApps.Add_Unchecked({ $script:wingetPanel.Visibility = 'Collapsed' }) $script:wingetPanel.Visibility = 'Visible'
# Don't show search panel here - it should only show after validation
})
$script:chkInstallWingetApps.Add_Unchecked({
$script:wingetPanel.Visibility = 'Collapsed'
$script:wingetSearchPanel.Visibility = 'Collapsed'
})
# Handle Winget component check/installation # Handle Winget component check/installation
$script:btnCheckWingetModule.Add_Click({ $script:btnCheckWingetModule.Add_Click({
@@ -958,6 +965,13 @@ $window.Add_Loaded({
# Update UI with final status # Update UI with final status
Update-WingetVersionFields -wingetText $cliStatus.Status -moduleText $module.Version Update-WingetVersionFields -wingetText $cliStatus.Status -moduleText $module.Version
# Show search panel only if versions are valid and checkbox is still checked
if ($cliStatus.Status -match '^\d+\.\d+\.\d+$' -and
$module.Version -match '^\d+\.\d+\.\d+$' -and
$script:chkInstallWingetApps.IsChecked) {
$script:wingetSearchPanel.Visibility = 'Visible'
}
} }
catch { catch {
Update-WingetVersionFields -wingetText "Error" -moduleText "Error" Update-WingetVersionFields -wingetText "Error" -moduleText "Error"
@@ -974,8 +988,199 @@ $window.Add_Loaded({
} }
}) })
}) })
# Create Winget Search section (initially hidden)
$script:wingetSearchPanel = $window.FindName('wingetSearchPanel')
$script:txtWingetSearch = $window.FindName('txtWingetSearch')
$script:btnWingetSearch = $window.FindName('btnWingetSearch')
$script:lstWingetResults = $window.FindName('lstWingetResults')
$script:btnSaveWingetList = $window.FindName('btnSaveWingetList')
$script:btnImportWingetList = $window.FindName('btnImportWingetList')
# Initialize ListView with GridView columns
$gridView = New-Object System.Windows.Controls.GridView
Add-SortableColumn -gridView $gridView -header "Selected" -binding "IsSelected" -width 60 -isCheckbox $true
Add-SortableColumn -gridView $gridView -header "Name" -binding "Name" -width 200
Add-SortableColumn -gridView $gridView -header "Id" -binding "Id" -width 200
Add-SortableColumn -gridView $gridView -header "Version" -binding "Version" -width 100
Add-SortableColumn -gridView $gridView -header "Source" -binding "Source" -width 100
$script:lstWingetResults.View = $gridView
# Hide search panel initially
$script:wingetSearchPanel.Visibility = 'Collapsed'
# Add search functionality
$script:btnWingetSearch.Add_Click({
Search-WingetApps
})
$script:txtWingetSearch.Add_KeyDown({
param($eventSrc, $keyEvent)
if ($keyEvent.Key -eq 'Return') {
Search-WingetApps
$keyEvent.Handled = $true
}
})
# Save and Import buttons
$script:btnSaveWingetList.Add_Click({
Save-WingetList
})
$script:btnImportWingetList.Add_Click({
Import-WingetList
})
# Show search panel after successful Winget validation
$script:btnCheckWingetModule.Add_Click({
# ...existing code...
try {
# Check Winget CLI first
$cliStatus = Test-WingetCLI
# Install/Update PowerShell module if needed
$module = Install-WingetComponents -currentWingetVersion $cliStatus.Status
# Update UI with final status
Update-WingetVersionFields -wingetText $cliStatus.Status -moduleText $module.Version
# Show search panel if versions are valid
if ($cliStatus.Status -match '^\d+\.\d+\.\d+$' -and $module.Version -match '^\d+\.\d+\.\d+$') {
$script:wingetSearchPanel.Visibility = 'Visible'
}
}
catch {
# ...existing error handling code...
}
})
$script:lstWingetResults.Add_PreviewMouseLeftButtonUp({
param($eventSrc, $mouseEventArgs)
$originalSource = $mouseEventArgs.OriginalSource
$header = [System.Windows.Media.VisualTreeHelper]::GetParent($originalSource)
while ($header -ne $null -and $header -isnot [System.Windows.Controls.GridViewColumnHeader]) {
$header = [System.Windows.Media.VisualTreeHelper]::GetParent($header)
}
if ($header -is [System.Windows.Controls.GridViewColumnHeader]) {
$headerContent = $header.Column.Header
if ($headerContent -is [System.Windows.Controls.GridViewColumnHeader]) {
if ($headerContent.Tag) {
Invoke-ListViewSort -listView $script:lstWingetResults -property $headerContent.Tag
}
}
}
})
}) })
# Function to search for Winget apps
function Search-WingetApps {
try {
$searchQuery = $script:txtWingetSearch.Text
if ([string]::IsNullOrWhiteSpace($searchQuery)) { return }
# Store selected apps
$selectedApps = $script:lstWingetResults.Items | Where-Object { $_.IsSelected }
# Search for new apps
$results = Find-WingetPackage -Query $searchQuery | ForEach-Object {
[PSCustomObject]@{
IsSelected = $false
Name = $_.Name
Id = $_.Id
Version = $_.Version
Source = $_.Source
}
}
# Clear and repopulate list view
$script:lstWingetResults.Items.Clear()
# Add back selected apps first
foreach ($app in $selectedApps) {
$script:lstWingetResults.Items.Add($app)
# Remove from new results if already selected
$results = $results | Where-Object { $_.Id -ne $app.Id }
}
# Add new search results
foreach ($result in $results) {
$script:lstWingetResults.Items.Add($result)
}
}
catch {
[System.Windows.MessageBox]::Show("Error searching for apps: $_", "Error", "OK", "Error")
}
}
# Function to save selected apps to JSON
function Save-WingetList {
try {
$selectedApps = $script:lstWingetResults.Items | Where-Object { $_.IsSelected }
if (-not $selectedApps) {
[System.Windows.MessageBox]::Show("No apps selected to save.", "Warning", "OK", "Warning")
return
}
$appList = @{
apps = @($selectedApps | ForEach-Object {
[ordered]@{
name = $_.Name
id = $_.Id
source = $_.Source.ToLower()
}
})
}
$sfd = New-Object System.Windows.Forms.SaveFileDialog
$sfd.Filter = "JSON files (*.json)|*.json"
$sfd.Title = "Save App List"
$sfd.InitialDirectory = $AppsPath
$sfd.FileName = "AppList.json"
if ($sfd.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
$appList | ConvertTo-Json -Depth 10 | Set-Content $sfd.FileName -Encoding UTF8
[System.Windows.MessageBox]::Show("App list saved successfully.", "Success", "OK", "Information")
}
}
catch {
[System.Windows.MessageBox]::Show("Error saving app list: $_", "Error", "OK", "Error")
}
}
# Function to import app list from JSON
function Import-WingetList {
try {
$ofd = New-Object System.Windows.Forms.OpenFileDialog
$ofd.Filter = "JSON files (*.json)|*.json"
$ofd.Title = "Import App List"
$ofd.InitialDirectory = $AppsPath
if ($ofd.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
$importedApps = Get-Content $ofd.FileName -Raw | ConvertFrom-Json
# Clear existing items
$script:lstWingetResults.Items.Clear()
# Add imported apps
foreach ($app in $importedApps.apps) {
$script:lstWingetResults.Items.Add([PSCustomObject]@{
IsSelected = $true
Name = $app.name
Id = $app.id
Version = "" # Will be populated when searching
Source = $app.source
})
}
[System.Windows.MessageBox]::Show("App list imported successfully.", "Success", "OK", "Information")
}
}
catch {
[System.Windows.MessageBox]::Show("Error importing app list: $_", "Error", "OK", "Error")
}
}
# Button: Build FFU # Button: Build FFU
$btnRun = $window.FindName('btnRun') $btnRun = $window.FindName('btnRun')
$btnRun.Add_Click({ $btnRun.Add_Click({
+52
View File
@@ -598,6 +598,58 @@
ToolTip="Check installation status and version of Winget CLI and PowerShell module. Will install or update if needed."/> ToolTip="Check installation status and version of Winget CLI and PowerShell module. Will install or update if needed."/>
</Grid> </Grid>
</StackPanel> </StackPanel>
<!-- Winget Search Panel -->
<StackPanel x:Name="wingetSearchPanel"
Visibility="Collapsed"
Margin="25,10,5,5">
<TextBlock Text="Winget Search"
FontWeight="Bold"
Margin="0,0,0,5"/>
<Grid Margin="0,0,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="txtWingetSearch"
Grid.Column="0"
Margin="0,0,10,0"
Height="24"
VerticalContentAlignment="Center"
VerticalAlignment="Center"
ToolTip="Enter an application name to search for"/>
<Button x:Name="btnWingetSearch"
Grid.Column="1"
Content="Search"
Width="100"
Height="24"
ToolTip="Search for applications using Windows Package Manager"/>
</Grid>
<!-- Results ListView -->
<ListView x:Name="lstWingetResults"
Height="300"
Margin="0,0,0,10"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto"/>
<!-- Save/Import Buttons -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Button x:Name="btnSaveWingetList"
Content="Save Applist.json"
Padding="15,5"
Margin="0,0,10,0"
ToolTip="Save selected applications to a JSON file"/>
<Button x:Name="btnImportWingetList"
Content="Import Applist.json"
Padding="15,5"
ToolTip="Import applications from a JSON file"/>
</StackPanel>
</StackPanel>
</StackPanel> </StackPanel>
</Grid> </Grid>
</TabItem> </TabItem>