Consolidate WinGet version detection

Add a shared WinGet component status helper that uses Get-WinGetVersion
through Microsoft.WinGet.Client, and route both the CLI and UI status checks
through it. This removes the UI-only winget.exe --version parsing path and
adds clearer logging for missing modules, missing cmdlets, parse failures,
and caught WinGet version errors.
This commit is contained in:
rbalsleyMSFT
2026-06-05 13:35:07 -07:00
parent 895728ebe8
commit 56a2597818
2 changed files with 145 additions and 66 deletions
+118 -12
View File
@@ -1023,6 +1023,94 @@ function Install-WinGet {
}
WriteLog "WinGet installation complete."
}
function Get-WinGetComponentStatus {
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[version]$MinimumVersion = [version]"1.8.1911"
)
$moduleName = 'Microsoft.WinGet.Client'
$status = [PSCustomObject]@{
Success = $false
NeedsUpdate = $true
WinGetInstalled = $false
WinGetNeedsUpdate = $true
WinGetVersion = "Unknown"
WinGetVersionObject = $null
WinGetStatus = "Unknown"
ModuleInstalled = $false
ModuleNeedsUpdate = $true
ModuleVersion = "Not installed"
ModuleVersionObject = $null
CmdletAvailable = $false
ErrorMessage = ""
}
try {
$installedModule = @(Get-InstalledModule -Name $moduleName -ErrorAction SilentlyContinue) | Sort-Object -Property Version -Descending | Select-Object -First 1
$availableModule = @(Get-Module -ListAvailable -Name $moduleName -ErrorAction SilentlyContinue) | Sort-Object -Property Version -Descending | Select-Object -First 1
$wingetModule = if ($null -ne $installedModule) { $installedModule } else { $availableModule }
if ($null -eq $wingetModule) {
$status.WinGetStatus = "$moduleName module is not installed."
WriteLog $status.WinGetStatus
return $status
}
$status.ModuleInstalled = $true
$status.ModuleVersion = $wingetModule.Version.ToString()
$status.ModuleVersionObject = [version]$wingetModule.Version
$status.ModuleNeedsUpdate = $status.ModuleVersionObject -lt $MinimumVersion
WriteLog "$moduleName module version detected: $($status.ModuleVersion)"
Import-Module -Name $moduleName -Force -ErrorAction Stop
$wingetVersionCommand = Get-Command -Name Get-WinGetVersion -ErrorAction SilentlyContinue
if ($null -eq $wingetVersionCommand) {
$status.WinGetStatus = "Get-WinGetVersion cmdlet is not available."
$status.ErrorMessage = $status.WinGetStatus
WriteLog $status.WinGetStatus
return $status
}
$status.CmdletAvailable = $true
$wingetVersion = Get-WinGetVersion -ErrorAction Stop
$wingetVersionText = [string]$wingetVersion
WriteLog "Get-WinGetVersion returned: $wingetVersionText"
if ([string]::IsNullOrWhiteSpace($wingetVersionText)) {
$status.WinGetVersion = "Not installed"
$status.WinGetStatus = "WinGet is not installed."
WriteLog $status.WinGetStatus
return $status
}
if ($wingetVersionText -match 'v?(\d+\.\d+\.\d+)') {
$parsedVersion = [version]$matches[1]
$status.WinGetInstalled = $true
$status.WinGetVersion = $parsedVersion.ToString()
$status.WinGetVersionObject = $parsedVersion
$status.WinGetNeedsUpdate = $parsedVersion -lt $MinimumVersion
$status.WinGetStatus = if ($status.WinGetNeedsUpdate) { "Update required" } else { $parsedVersion.ToString() }
$status.NeedsUpdate = $status.ModuleNeedsUpdate -or $status.WinGetNeedsUpdate
$status.Success = -not $status.NeedsUpdate
return $status
}
$status.WinGetStatus = "Version check failed."
$status.ErrorMessage = "Could not parse Get-WinGetVersion output: $wingetVersionText"
WriteLog $status.ErrorMessage
return $status
}
catch {
$status.ErrorMessage = $_.Exception.Message
$status.WinGetStatus = "Get-WinGetVersion failed."
WriteLog "Get-WinGetVersion failed: $($status.ErrorMessage)"
return $status
}
}
function Confirm-WinGetInstallation {
[CmdletBinding()]
param(
@@ -1032,12 +1120,11 @@ function Confirm-WinGetInstallation {
WriteLog 'Checking if WinGet is installed...'
$minVersion = [version]"1.8.1911"
$wingetStatus = Get-WinGetComponentStatus -MinimumVersion $minVersion
# Check WinGet PowerShell module
$wingetModule = Get-InstalledModule -Name Microsoft.Winget.Client -ErrorAction SilentlyContinue
$wingetModuleVersion = [version]$wingetModule.Version
if ($wingetModuleVersion -lt $minVersion -or -not $wingetModule) {
WriteLog 'Microsoft.Winget.Client module is not installed or is an older version. Installing the latest version...'
if ($wingetStatus.ModuleNeedsUpdate) {
WriteLog 'Microsoft.WinGet.Client module is not installed or is an older version. Installing the latest version...'
# Handle PSGallery trust settings
$PSGalleryTrust = (Get-PSRepository -Name 'PSGallery').InstallationPolicy
@@ -1046,30 +1133,49 @@ function Confirm-WinGetInstallation {
Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted
}
Install-Module -Name Microsoft.Winget.Client -Force -Repository 'PSGallery'
Install-Module -Name Microsoft.WinGet.Client -Force -Repository 'PSGallery'
if ($PSGalleryTrust -eq 'Untrusted') {
WriteLog 'Setting PSGallery back to untrusted repository...'
Set-PSRepository -Name 'PSGallery' -InstallationPolicy Untrusted
WriteLog 'Done'
}
$wingetStatus = Get-WinGetComponentStatus -MinimumVersion $minVersion
}
else {
WriteLog "Installed Microsoft.Winget.Client module version: $($wingetModule.Version)"
WriteLog "Installed Microsoft.WinGet.Client module version: $($wingetStatus.ModuleVersion)"
}
if ($wingetStatus.ModuleNeedsUpdate) {
$message = "Microsoft.WinGet.Client module version $($wingetStatus.ModuleVersion) does not meet the minimum required version $minVersion."
WriteLog $message
throw $message
}
if (-not $wingetStatus.CmdletAvailable) {
$message = "Get-WinGetVersion cmdlet is not available from Microsoft.WinGet.Client. $($wingetStatus.ErrorMessage)"
WriteLog $message
throw $message
}
if (-not [string]::IsNullOrWhiteSpace($wingetStatus.ErrorMessage)) {
$message = "Unable to determine WinGet version by using Get-WinGetVersion. $($wingetStatus.ErrorMessage)"
WriteLog $message
throw $message
}
# Check WinGet CLI
$wingetVersion = Get-WinGetVersion
if (-not $wingetVersion) {
if (-not $wingetStatus.WinGetInstalled) {
WriteLog "WinGet is not installed. Installing WinGet..."
Install-WinGet -Architecture $WindowsArch
}
elseif ($wingetVersion -match 'v?(\d+\.\d+\.\d+)' -and [version]$matches[1] -lt $minVersion) {
WriteLog "The installed version of WinGet $($matches[1]) does not support downloading MSStore apps. Installing the latest version of WinGet..."
elseif ($wingetStatus.WinGetNeedsUpdate) {
WriteLog "The installed version of WinGet $($wingetStatus.WinGetVersion) does not support downloading MSStore apps. Installing the latest version of WinGet..."
Install-WinGet -Architecture $WindowsArch
}
else {
WriteLog "Installed WinGet version: $wingetVersion"
WriteLog "Installed WinGet version: $($wingetStatus.WinGetVersion)"
}
}
# --------------------------------------------------------------------------
@@ -1561,4 +1667,4 @@ function Add-Win32SilentInstallCommand {
# --------------------------------------------------------------------------
# Export functions needed by both BuildFFUVM and the UI Core module
Export-ModuleMember -Function Get-Application, Get-Apps, Start-WingetAppDownloadTask, Confirm-WinGetInstallation, Add-Win32SilentInstallCommand, Install-Winget
Export-ModuleMember -Function Get-Application, Get-Apps, Start-WingetAppDownloadTask, Confirm-WinGetInstallation, Get-WinGetComponentStatus, Add-Win32SilentInstallCommand, Install-Winget
@@ -233,44 +233,6 @@ function Search-WingetPackagesPublic {
}
}
function Test-WingetCLI {
[CmdletBinding()]
param()
$minVersion = [version]"1.8.1911"
# Check Winget CLI
$wingetCmd = Get-Command -Name winget -ErrorAction SilentlyContinue
if (-not $wingetCmd) {
return @{
Version = "Not installed"
Status = "Not installed - Install from Microsoft Store"
}
}
# Get and check version
$wingetVersion = & winget.exe --version
if ($wingetVersion -match 'v?(\d+\.\d+.\d+)') {
$version = [version]$matches[1]
if ($version -lt $minVersion) {
return @{
Version = $version.ToString()
Status = "Update required - Install from Microsoft Store"
}
}
return @{
Version = $version.ToString()
Status = $version.ToString()
}
}
return @{
Version = "Unknown"
Status = "Version check failed"
}
}
function Install-WingetComponents {
[CmdletBinding()]
param(
@@ -339,19 +301,22 @@ function Confirm-WingetInstallationUI {
try {
# Initial Check
WriteLog "Confirm-WingetInstallationUI: Starting checks..."
$cliStatus = Test-WingetCLI
$module = @(Get-InstalledModule -Name Microsoft.WinGet.Client -ErrorAction SilentlyContinue) | Sort-Object -Top 1 -Descending Version -ErrorAction SilentlyContinue
$wingetStatus = Get-WinGetComponentStatus -MinimumVersion $minVersion
$result.CliVersion = $cliStatus.Version
$result.ModuleVersion = if ($null -ne $module) { $module.Version.ToString() } else { "Not installed" }
$result.CliVersion = $wingetStatus.WinGetVersion
$result.ModuleVersion = $wingetStatus.ModuleVersion
# Use callback for initial status display
& $UiUpdateCallback $result.CliVersion $result.ModuleVersion
# Determine if install/update is needed
$needsCliUpdate = $cliStatus.Status -notmatch '^\d+\.\d+\.\d+$' -or ([version]$cliStatus.Version -lt $minVersion)
$needsModuleUpdate = ($null -eq $module) -or ([version]$module.Version -lt $minVersion)
$result.NeedsUpdate = $needsCliUpdate -or $needsModuleUpdate
$needsCliUpdate = $wingetStatus.WinGetNeedsUpdate
$needsModuleUpdate = $wingetStatus.ModuleNeedsUpdate
$result.NeedsUpdate = $wingetStatus.NeedsUpdate
if (-not [string]::IsNullOrWhiteSpace($wingetStatus.ErrorMessage)) {
WriteLog "Confirm-WingetInstallationUI: WinGet status error - $($wingetStatus.ErrorMessage)"
}
if ($result.NeedsUpdate) {
WriteLog "Confirm-WingetInstallationUI: Update needed. CLI Needs Update: $needsCliUpdate, Module Needs Update: $needsModuleUpdate"
@@ -361,21 +326,29 @@ function Confirm-WingetInstallationUI {
& $UiUpdateCallback $result.CliVersion "Installing/Updating..."
# Attempt to install/update Winget CLI and module
$installedModule = Install-WingetComponents -UiUpdateCallback $UiUpdateCallback
Install-WingetComponents -UiUpdateCallback $UiUpdateCallback | Out-Null
# Re-check status after attempt
WriteLog "Confirm-WingetInstallationUI: Re-checking status after update attempt..."
$cliStatus = Test-WingetCLI
$result.CliVersion = $cliStatus.Version
$result.ModuleVersion = if ($null -ne $installedModule) { $installedModule.Version } else { "Install Failed" }
$wingetStatus = Get-WinGetComponentStatus -MinimumVersion $minVersion
$result.CliVersion = $wingetStatus.WinGetVersion
$result.ModuleVersion = $wingetStatus.ModuleVersion
# Use callback for final status display after update attempt
& $UiUpdateCallback $result.CliVersion $result.ModuleVersion
# Check if update was successful
$cliOk = $cliStatus.Status -match '^\d+\.\d+\.\d+$' -and ([version]$cliStatus.Version -ge $minVersion)
$moduleOk = ($null -ne $installedModule) -and ([version]$installedModule.Version -ge $minVersion)
$result.Success = $cliOk -and $moduleOk
$result.Message = if ($result.Success) { "Winget components installed/updated successfully." } else { "Winget component installation/update failed or is incomplete." }
$cliOk = $wingetStatus.WinGetInstalled -and -not $wingetStatus.WinGetNeedsUpdate
$moduleOk = $wingetStatus.ModuleInstalled -and -not $wingetStatus.ModuleNeedsUpdate
$result.Success = $cliOk -and $moduleOk -and [string]::IsNullOrWhiteSpace($wingetStatus.ErrorMessage)
$result.Message = if ($result.Success) {
"Winget components installed/updated successfully."
}
elseif (-not [string]::IsNullOrWhiteSpace($wingetStatus.ErrorMessage)) {
"Winget component installation/update failed: $($wingetStatus.ErrorMessage)"
}
else {
"Winget component installation/update failed or is incomplete."
}
WriteLog "Confirm-WingetInstallationUI: Update attempt finished. Success: $($result.Success). Message: $($result.Message)"
}
else {