Private/WinGetRegistry.ps1
using module ./_EntryRegistry.psm1 [NoRunspaceAffinity()] class WinGetRegistry : EntryRegistry { $entries = [System.Collections.Generic.List[PowerShellRun.SelectorEntry]]::new() $subMenuEntries = [System.Collections.Generic.List[PowerShellRun.SelectorEntry]]::new() $isEntryUpdated = $false WinGetRegistry() { } [System.Collections.Generic.List[PowerShellRun.SelectorEntry]] GetEntries([String[]]$categories) { if ($categories -contains 'Utility') { return $this.entries } return $null } [void] InitializeEntries([String[]]$categories) { $enabled = $categories -contains 'Utility' $enabled = $enabled -and $this.IsWinGetInstalled() if ($enabled) { $this.RegisterEntries() } } [bool] IsWinGetInstalled() { $winGet = Get-Command -Name winget -Type Application -ErrorAction SilentlyContinue if (-not $winGet) { return $false } $winGetModule = Get-Module -Name Microsoft.WinGet.Client -ListAvailable if (-not $winGetModule) { return $false } return $true } [void] RegisterEntries() { $callback = { $thisClass = $args[0].ArgumentList $option = $script:globalStore.GetPSRunSelectorOption() $option.Prompt = 'WinGet (PSRun)' $option.QuitWithBackspaceOnEmptyQuery = $true $context = $null while ($true) { $result = Invoke-PSRunSelectorCustom -Entry $thisClass.subMenuEntries -Option $option -Context $context $context = $result.Context $entry = $result.FocusedEntry if (-not $entry) { return } if ($result.KeyCombination -eq $script:globalStore.firstActionKey) { & $entry.UserData.ScriptBlock $entry.UserData.ArgumentList } if ([PowerShellRun.ExitStatus]::Type -ne [PowerShellRun.ExitType]::QuitWithBackspaceOnEmptyQuery) { return } } } $topEntry = [PowerShellRun.SelectorEntry]::new() $topEntry.Icon = '📦' $topEntry.Name = 'WinGet (PSRun)' $topEntry.Description = 'Install and manage applications using winget' $topEntry.ActionKeys = @( [PowerShellRun.ActionKey]::new($script:globalStore.firstActionKey, 'Open WinGet menu') ) $topEntry.UserData = @{ ScriptBlock = $callback ArgumentList = $this } $this.entries.Add($topEntry) $this.subMenuEntries.Clear() $this.subMenuEntries.Add($this.CreateInstallEntry()) $this.subMenuEntries.Add($this.CreateUpgradeEntry()) $this.subMenuEntries.Add($this.CreateUninstallEntry()) $this.isEntryUpdated = $true } [PowerShellRun.SelectorEntry] CreatePackageEntry($package) { $entry = [PowerShellRun.SelectorEntry]::new() $entry.UserData = $package $entry.Icon = if ($_.Source -eq 'winget') { '📦' } elseif ($_.Source -eq 'msstore') { '🛒' } else { '🔧' } $entry.Name = $_.Name $entry.Description = if ($_.Source) { '[{0}] {1}' -f $_.Source, $_.Id } else { $_.Id } return $entry } [PowerShellRun.SelectorEntry] CreateInstallEntry() { $callback = { param ($thisClass) $option = $script:globalStore.GetPSRunSelectorOption() $option.QuitWithBackspaceOnEmptyQuery = $true $promptContext = $null $originalPrompt = $option.Prompt while ($true) { $option.Prompt = 'Type application name to search' $promptResult = Invoke-PSRunPrompt -Option $option -Context $promptContext $promptContext = $promptResult.Context if ($null -eq $promptResult.Input) { return } $option.Prompt = $originalPrompt $packages = Find-WinGetPackage -Query $promptResult.Input if (-not $packages) { Write-Warning -Message ('[{0}] No available application found.' -f $promptResult.Input) return } $actionKeys = @( [PowerShellRun.ActionKey]::new($script:globalStore.firstActionKey, 'Install with winget') [PowerShellRun.ActionKey]::new($script:globalStore.secondActionKey, 'Show information on the source') [PowerShellRun.ActionKey]::new($script:globalStore.copyActionKey, 'Copy install command to Clipboard') ) $result = $packages | ForEach-Object { $entry = $thisClass.CreatePackageEntry($_) $entry.ActionKeys = $actionKeys $entry.ActionKeysMultiSelection = $actionKeys $entry.Preview = 'Loading...' $entry.PreviewAsyncScript = { param ($package) $lines = & winget show --id $package.Id $lines | Where-Object { # winget produces empty lines and lines that only have '-' at the beginning. Remove them. $trimmedLine = $_.Trim() ($trimmedLine.Length -ne 0) -and ($trimmedLine[0] -ne '-') } } $entry.PreviewAsyncScriptArgumentList = $_ $entry } | Invoke-PSRunSelectorCustom -Option $option -MultiSelection if ([PowerShellRun.ExitStatus]::Type -eq [PowerShellRun.ExitType]::QuitWithBackspaceOnEmptyQuery) { continue } if ($result.MarkedEntries) { $installPackages = $result.MarkedEntries.UserData } else { $installPackages = $result.FocusedEntry.UserData } if (-not $installPackages) { return } if ($result.KeyCombination -eq $script:globalStore.firstActionKey) { $installPackages | ForEach-Object { Install-WinGetPackage -Id $_.Id } } elseif ($result.KeyCombination -eq $script:globalStore.secondActionKey) { $installPackages | ForEach-Object { & winget show --id $_.Id } } elseif ($result.KeyCombination -eq $script:globalStore.copyActionKey) { $command = @() $installPackages | ForEach-Object { $command += 'winget install --id {0}' -f $_.Id } $command | Set-Clipboard } return } } $entry = [PowerShellRun.SelectorEntry]::new() $entry.Icon = '🔽' $entry.Name = 'Install' $entry.Description = 'Open Install menu' $entry.ActionKeys = @( [PowerShellRun.ActionKey]::new($script:globalStore.firstActionKey, 'Open Install menu') ) $entry.UserData = @{ ScriptBlock = $callback ArgumentList = $this } return $entry } [PowerShellRun.SelectorEntry] CreateUpgradeEntry() { $callback = { param ($thisClass) $option = $script:globalStore.GetPSRunSelectorOption() $option.QuitWithBackspaceOnEmptyQuery = $true $packages = Get-WinGetPackage | Where-Object { $_.IsUpdateAvailable } if (-not $packages) { Write-Warning -Message 'No upgradable application found.' return } $actionKeys = @( [PowerShellRun.ActionKey]::new($script:globalStore.firstActionKey, 'Upgrade with winget') [PowerShellRun.ActionKey]::new($script:globalStore.secondActionKey, 'Show information on the source') [PowerShellRun.ActionKey]::new($script:globalStore.copyActionKey, 'Copy upgrade command to Clipboard') ) $result = $packages | ForEach-Object { $entry = $thisClass.CreatePackageEntry($_) $entry.ActionKeys = $actionKeys $entry.ActionKeysMultiSelection = $actionKeys $entry.Preview = $_ | Format-List | Out-String $entry } | Invoke-PSRunSelectorCustom -Option $option -MultiSelection if ($result.MarkedEntries) { $upgradePackages = $result.MarkedEntries.UserData } else { $upgradePackages = $result.FocusedEntry.UserData } if (-not $upgradePackages) { return } if ($result.KeyCombination -eq $script:globalStore.firstActionKey) { $upgradePackages | ForEach-Object { Update-WinGetPackage -Id $_.Id } } elseif ($result.KeyCombination -eq $script:globalStore.secondActionKey) { $upgradePackages | ForEach-Object { & winget show --id $_.Id } } elseif ($result.KeyCombination -eq $script:globalStore.copyActionKey) { $command = @() $upgradePackages | ForEach-Object { $command += 'winget upgrade --id {0}' -f $_.Id } $command | Set-Clipboard } } $entry = [PowerShellRun.SelectorEntry]::new() $entry.Icon = '💫' $entry.Name = 'Upgrade' $entry.Description = 'Open Upgrade menu' $entry.ActionKeys = @( [PowerShellRun.ActionKey]::new($script:globalStore.firstActionKey, 'Open Upgrade menu') ) $entry.UserData = @{ ScriptBlock = $callback ArgumentList = $this } return $entry } [PowerShellRun.SelectorEntry] CreateUninstallEntry() { $callback = { param ($thisClass) $option = $script:globalStore.GetPSRunSelectorOption() $option.QuitWithBackspaceOnEmptyQuery = $true $packages = Get-WinGetPackage if (-not $packages) { Write-Warning -Message 'No application found.' return } $actionKeysNoSource = @( [PowerShellRun.ActionKey]::new($script:globalStore.firstActionKey, 'Uninstall with winget') [PowerShellRun.ActionKey]::new($script:globalStore.copyActionKey, 'Copy uninstall command to Clipboard') ) $actionKeysWithSource = @( [PowerShellRun.ActionKey]::new($script:globalStore.firstActionKey, 'Uninstall with winget') [PowerShellRun.ActionKey]::new($script:globalStore.secondActionKey, 'Show information on the source') [PowerShellRun.ActionKey]::new($script:globalStore.copyActionKey, 'Copy uninstall command to Clipboard') ) $result = $packages | ForEach-Object { $entry = $thisClass.CreatePackageEntry($_) $entry.ActionKeys = if ($_.Source) { $actionKeysWithSource } else { $actionKeysNoSource } $entry.ActionKeysMultiSelection = $actionKeys $entry.Preview = $_ | Format-List | Out-String $entry } | Invoke-PSRunSelectorCustom -Option $option -MultiSelection if ($result.MarkedEntries) { $uninstallPackages = $result.MarkedEntries.UserData } else { $uninstallPackages = $result.FocusedEntry.UserData } if (-not $uninstallPackages) { return } if ($result.KeyCombination -eq $script:globalStore.firstActionKey) { $uninstallPackages | ForEach-Object { if ($thisClass.IsUninstallableWithVersion($_)) { Uninstall-WinGetPackage -Id $_.Id -Version $_.InstalledVersion -Confirm } else { Uninstall-WinGetPackage -Id $_.Id -Confirm } } } elseif ($result.KeyCombination -eq $script:globalStore.secondActionKey) { $uninstallPackages | ForEach-Object { & winget show --id $_.Id } } elseif ($result.KeyCombination -eq $script:globalStore.copyActionKey) { $command = @() $uninstallPackages | ForEach-Object { if ($thisClass.IsUninstallableWithVersion($_)) { $command += 'winget uninstall --id {0} --version {1}' -f $_.Id, $_.InstalledVersion } else { $command += 'winget uninstall --id {0}' -f $_.Id } } $command | Set-Clipboard } } $entry = [PowerShellRun.SelectorEntry]::new() $entry.Icon = '⛔' $entry.Name = 'Uninstall' $entry.Description = 'Open Uninstall menu' $entry.ActionKeys = @( [PowerShellRun.ActionKey]::new($script:globalStore.firstActionKey, 'Open Uninstall menu') ) $entry.UserData = @{ ScriptBlock = $callback ArgumentList = $this } return $entry } [bool] IsUninstallableWithVersion($package) { # side by side is still in preview as of winget v1.7.10861. return $false <# if (-not $package.InstalledVersion) { return $false } return $package.Source -eq 'winget' #> } [bool] UpdateEntries() { $updated = $this.isEntryUpdated $this.isEntryUpdated = $false return $updated } } |