diff --git a/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/WinGetPackageManagerCommand.cs b/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/WinGetPackageManagerCommand.cs index cdf5f16d51..b08e70ce60 100644 --- a/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/WinGetPackageManagerCommand.cs +++ b/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/WinGetPackageManagerCommand.cs @@ -21,7 +21,7 @@ namespace Microsoft.WinGet.Client.Engine.Commands /// /// Used by Repair-WinGetPackageManager and Assert-WinGetPackageManager. /// - public sealed class WinGetPackageManagerCommand : BaseCommand + public sealed class WinGetPackageManagerCommand : ManagementDeploymentCommand { private const string EnvPath = "env:PATH"; @@ -132,7 +132,7 @@ private async Task RepairStateMachineAsync(string expectedVersion, bool allUsers switch (currentCategory) { case IntegrityCategory.UnexpectedVersion: - await this.InstallDifferentVersionAsync(new WinGetVersion(expectedVersion), allUsers, force); + await this.InstallDifferentVersionAsync(new WinGetVersion(expectedVersion), e.InstalledVersion, allUsers, force); break; case IntegrityCategory.NotInPath: this.RepairEnvPath(); @@ -167,9 +167,13 @@ private async Task RepairStateMachineAsync(string expectedVersion, bool allUsers } } - private async Task InstallDifferentVersionAsync(WinGetVersion toInstallVersion, bool allUsers, bool force) + private async Task InstallDifferentVersionAsync(WinGetVersion toInstallVersion, WinGetVersion? installedVersion, bool allUsers, bool force) { - var installedVersion = WinGetVersion.InstalledWinGetVersion(this); + if (installedVersion == null) + { + installedVersion = WinGetVersion.InstalledWinGetVersion(this); + } + bool isDowngrade = installedVersion.CompareAsDeployment(toInstallVersion) > 0; string message = $"Installed WinGet version '{installedVersion.TagVersion}' " + diff --git a/src/PowerShell/Microsoft.WinGet.Client.Engine/Common/WinGetIntegrity.cs b/src/PowerShell/Microsoft.WinGet.Client.Engine/Common/WinGetIntegrity.cs index 9669da8dbc..d9ff12bb56 100644 --- a/src/PowerShell/Microsoft.WinGet.Client.Engine/Common/WinGetIntegrity.cs +++ b/src/PowerShell/Microsoft.WinGet.Client.Engine/Common/WinGetIntegrity.cs @@ -39,13 +39,14 @@ public static void AssertWinGet(PowerShellCmdlet pwshCmdlet, string expectedVers return; } + WinGetCLICommandResult? versionResult = null; + try { // Start by calling winget without its WindowsApp PFN path. // If it succeeds and the exit code is 0 then we are good. - var wingetCliWrapper = new WingetCLIWrapper(false); - var result = wingetCliWrapper.RunCommand(pwshCmdlet, "--version"); - result.VerifyExitCode(); + versionResult = WinGetVersion.RunWinGetVersionFromCLI(pwshCmdlet, false); + versionResult.VerifyExitCode(); } catch (Win32Exception e) { @@ -68,7 +69,7 @@ public static void AssertWinGet(PowerShellCmdlet pwshCmdlet, string expectedVers { // This assumes caller knows that the version exist. WinGetVersion expectedWinGetVersion = new WinGetVersion(expectedVersion); - var installedVersion = WinGetVersion.InstalledWinGetVersion(pwshCmdlet); + var installedVersion = WinGetVersion.InstalledWinGetVersion(pwshCmdlet, versionResult); if (expectedWinGetVersion.CompareTo(installedVersion) != 0) { throw new WinGetIntegrityException( @@ -76,7 +77,8 @@ public static void AssertWinGet(PowerShellCmdlet pwshCmdlet, string expectedVers string.Format( Resources.IntegrityUnexpectedVersionMessage, installedVersion.TagVersion, - expectedVersion)); + expectedVersion)) + { InstalledVersion = installedVersion }; } } } diff --git a/src/PowerShell/Microsoft.WinGet.Client.Engine/Exceptions/WinGetIntegrityException.cs b/src/PowerShell/Microsoft.WinGet.Client.Engine/Exceptions/WinGetIntegrityException.cs index 63a7939038..4ffee8283d 100644 --- a/src/PowerShell/Microsoft.WinGet.Client.Engine/Exceptions/WinGetIntegrityException.cs +++ b/src/PowerShell/Microsoft.WinGet.Client.Engine/Exceptions/WinGetIntegrityException.cs @@ -1,4 +1,4 @@ -// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. Licensed under the MIT License. // @@ -9,6 +9,7 @@ namespace Microsoft.WinGet.Client.Engine.Exceptions using System; using System.Management.Automation; using Microsoft.WinGet.Client.Engine.Common; + using Microsoft.WinGet.Client.Engine.Helpers; using Microsoft.WinGet.Resources; /// @@ -53,6 +54,11 @@ public WinGetIntegrityException(IntegrityCategory category, string message) /// public IntegrityCategory Category { get; } + /// + /// Gets or sets the installed version. + /// + internal WinGetVersion? InstalledVersion { get; set; } + private static string GetMessage(IntegrityCategory category) => category switch { IntegrityCategory.Failure => Resources.IntegrityFailureMessage, diff --git a/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WinGetVersion.cs b/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WinGetVersion.cs index 19d4704dd5..1961df90f1 100644 --- a/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WinGetVersion.cs +++ b/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WinGetVersion.cs @@ -64,23 +64,39 @@ public WinGetVersion(string version) /// public bool IsPrerelease { get; } + /// + /// Runs the winget version command. + /// + /// PowerShell cmdlet. + /// Use full path or not. + /// The command result. + public static WinGetCLICommandResult RunWinGetVersionFromCLI(PowerShellCmdlet pwshCmdlet, bool fullPath = true) + { + var wingetCliWrapper = new WingetCLIWrapper(fullPath); + return wingetCliWrapper.RunCommand(pwshCmdlet, "--version"); + } + /// /// Gets the version of the installed winget. /// /// PowerShell cmdlet. + /// A command result from running previously. /// The WinGetVersion. - public static WinGetVersion InstalledWinGetVersion(PowerShellCmdlet pwshCmdlet) + public static WinGetVersion InstalledWinGetVersion(PowerShellCmdlet pwshCmdlet, WinGetCLICommandResult? versionResult = null) { - // Try getting the version through COM if it is available (user might have an older build installed) - string? comVersion = PackageManagerWrapper.Instance.GetVersion(); - if (comVersion != null) + if (versionResult == null || versionResult.ExitCode != 0) { - return new WinGetVersion(comVersion); + // Try getting the version through COM if it is available (user might have an older build installed) + string? comVersion = PackageManagerWrapper.Instance.GetVersion(); + if (comVersion != null) + { + return new WinGetVersion(comVersion); + } + + versionResult = RunWinGetVersionFromCLI(pwshCmdlet); } - var wingetCliWrapper = new WingetCLIWrapper(); - var result = wingetCliWrapper.RunCommand(pwshCmdlet, "--version"); - return new WinGetVersion(result.StdOut.Replace(Environment.NewLine, string.Empty)); + return new WinGetVersion(versionResult.StdOut.Replace(Environment.NewLine, string.Empty)); } ///