Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/windows/package-manager/winget/returnCodes.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ ms.localizationpriority: medium
| 0x8A15008B | -1979335093 | APPINSTALLER_CLI_ERROR_FONT_UNINSTALL_FAILED | Font uninstall failed. The font may not be in a good state. Try uninstalling after a restart. |
| 0x8A15008C | -1979335092 | APPINSTALLER_CLI_ERROR_FONT_VALIDATION_FAILED | Font validation failed. |
| 0x8A15008D | -1979335091 | APPINSTALLER_CLI_ERROR_FONT_ROLLBACK_FAILED | Font rollback failed. The font may not be in a good state. Try uninstalling after a restart. |
| 0x8A15008E | -1979335090 | APPINSTALLER_CLI_ERROR_UPDATE_INSTALL_TECHNOLOGY_MISMATCH | An upgrade is available but uses a different install technology than the current installation |
| 0x8A15008F | -1979335089 | APPINSTALLER_CLI_ERROR_UPGRADE_INSTALLED_VERSION_MISMATCH | Installer reported success but the installed version is still older than the upgrade target |

## Install errors.

Expand Down
2 changes: 2 additions & 0 deletions src/AppInstallerCLICore/Resources.h
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,8 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeDifferentInstallTechnology);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeDifferentInstallTechnologyInNewerVersions);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeInstallTechnologyMismatchCount);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeInstalledVersionMismatch);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeIsPinned);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradePinnedByUserCount);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeRequireExplicitCount);
Expand Down
42 changes: 42 additions & 0 deletions src/AppInstallerCLICore/Workflows/InstallFlow.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#include "pch.h"
#include <AppInstallerErrors.h>
#include "InstallFlow.h"
#include "DownloadFlow.h"
#include "FontFlow.h"
Expand All @@ -20,6 +21,7 @@
#include "SourceFlow.h"
#include <AppInstallerMsixInfo.h>
#include <AppInstallerDeployment.h>
#include <AppInstallerVersions.h>
#include <AppInstallerSynchronization.h>
#include <Argument.h>
#include <Command.h>
Expand Down Expand Up @@ -59,6 +61,36 @@ namespace AppInstaller::CLI::Workflow
}
}

// After a successful installer exit code, confirms ARP/MSIX reports at least the manifest version (upgrade only).
void VerifyUpgradeInstalledVersion(
Execution::Context& context,
std::string_view installedVersionString,
const Manifest::Manifest& manifest)
{
if (!WI_IsFlagSet(context.GetFlags(), Execution::ContextFlag::InstallerExecutionUseUpdate))
{
return;
}
if (WI_IsFlagSet(context.GetFlags(), Execution::ContextFlag::RebootRequired))
{
return;
}

Version expectedVersion{ manifest.Version };
Version installedVersion{ std::string{ installedVersionString } };
if (expectedVersion.IsUnknown() || installedVersion.IsUnknown())
{
return;
}
if (installedVersion < expectedVersion)
{
context.Reporter.Error() << Resource::String::UpgradeInstalledVersionMismatch(
Utility::LocIndString{ std::string{ manifest.Version } },
Utility::LocIndString{ std::string{ installedVersionString } }) << std::endl;
AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_UPGRADE_INSTALLED_VERSION_MISMATCH);
}
}

bool ShouldUseDirectMSIInstall(InstallerTypeEnum type, bool isSilentInstall)
{
switch (type)
Expand Down Expand Up @@ -886,6 +918,11 @@ namespace AppInstaller::CLI::Workflow

if (installer && !installer->PackageFamilyName.empty() && Deployment::IsRegistered(installer->PackageFamilyName))
{
const auto& manifest = context.Get<Execution::Data::Manifest>();
if (auto installedVersion = Deployment::GetInstalledVersionStringForFamilyName(installer->PackageFamilyName))
{
VerifyUpgradeInstalledVersion(context, *installedVersion, manifest);
}
return;
}

Expand All @@ -898,6 +935,11 @@ namespace AppInstaller::CLI::Workflow
// Store the ARP entry found to match the package to record it in the tracking catalog later
if (correlationResult.Package)
{
VerifyUpgradeInstalledVersion(
context,
correlationResult.Package->GetProperty(PackageVersionProperty::Version).get(),
manifest);

std::vector<AppsAndFeaturesEntry> entries;

auto metadata = correlationResult.Package->GetMetadata();
Expand Down
14 changes: 14 additions & 0 deletions src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw
Original file line number Diff line number Diff line change
Expand Up @@ -1345,6 +1345,14 @@ Please specify one of them using the --source option to proceed.</value>
<data name="UpgradeDifferentInstallTechnologyInNewerVersions" xml:space="preserve">
<value>A newer version was found, but the install technology is different from the current version installed. Please uninstall the package and install the newer version.</value>
</data>
<data name="UpgradeInstallTechnologyMismatchCount" xml:space="preserve">
<value>{0} package(s) have upgrades blocked because newer versions use a different install technology than the current installation. Uninstall each package, then install the newer version.</value>
<comment>{Locked="{0}"} {0} is the number of packages skipped for this reason during winget upgrade --all.</comment>
</data>
<data name="UpgradeInstalledVersionMismatch" xml:space="preserve">
<value>The installer reported success, but the installed version is still {1}. The upgrade target was {0}.</value>
<comment>{Locked="{0}","{1}"} {0} is the expected package version from the manifest; {1} is the version reported by Windows after install.</comment>
</data>
<data name="UpgradeDifferentInstallTechnology" xml:space="preserve">
<value>The install technology of the newer version specified is different from the current version installed. Please uninstall the package and install the newer version.</value>
</data>
Expand Down Expand Up @@ -2265,6 +2273,12 @@ Please specify one of them using the --source option to proceed.</value>
<data name="APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE" xml:space="preserve">
<value>No applicable update found</value>
</data>
<data name="APPINSTALLER_CLI_ERROR_UPDATE_INSTALL_TECHNOLOGY_MISMATCH" xml:space="preserve">
<value>An upgrade is available but uses a different install technology than the current installation</value>
</data>
<data name="APPINSTALLER_CLI_ERROR_UPGRADE_INSTALLED_VERSION_MISMATCH" xml:space="preserve">
<value>Installer reported success but the installed version is still older than the upgrade target</value>
</data>
<data name="APPINSTALLER_CLI_ERROR_UPDATE_ALL_HAS_FAILURE" xml:space="preserve">
<value>winget upgrade --all completed with failures</value>
</data>
Expand Down
24 changes: 24 additions & 0 deletions src/AppInstallerCommonCore/Deployment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,30 @@ namespace AppInstaller::Deployment
return packages.begin() != packages.end();
}

std::optional<std::string> GetInstalledVersionStringForFamilyName(std::string_view packageFamilyName)
{
try
{
std::wstring wideFamilyName = Utility::ConvertToUTF16(packageFamilyName);

PackageManager packageManager;
auto packages = packageManager.FindPackagesForUser({}, wideFamilyName);
auto it = packages.begin();
if (it == packages.end())
{
return std::nullopt;
}

const auto& v = it->Id().Version();
std::ostringstream stream;
stream << v.Major << '.' << v.Minor << '.' << v.Build << '.' << v.Revision;
return stream.str();
}
CATCH_LOG();

return std::nullopt;
}

void RegisterPackage(
std::string_view packageFamilyName,
IProgressCallback& callback)
Expand Down
6 changes: 6 additions & 0 deletions src/AppInstallerCommonCore/Public/AppInstallerDeployment.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// Licensed under the MIT License.
#pragma once
#include <AppInstallerProgress.h>
#include <optional>
#include <string>
#include <string_view>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Management.Deployment.h>

Expand Down Expand Up @@ -61,6 +64,9 @@ namespace AppInstaller::Deployment
// Calls winrt::Windows::Management::Deployment::PackageManager::FindPackagesForUser
bool IsRegistered(std::string_view packageFamilyName);

// Returns the version string (major.minor.build.revision) for the first package found for the family name, if any.
std::optional<std::string> GetInstalledVersionStringForFamilyName(std::string_view packageFamilyName);

// Calls winrt::Windows::Management::Deployment::PackageManager::RegisterPackageByFamilyNameAsync
void RegisterPackage(
std::string_view packageFamilyName,
Expand Down
2 changes: 2 additions & 0 deletions src/AppInstallerSharedLib/Errors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ namespace AppInstaller
WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_MANIFEST_VALIDATION_FAILURE, "Manifest validation failed"),
WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INVALID_MANIFEST, "Manifest is invalid"),
WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE, "No applicable update found"),
WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_UPDATE_INSTALL_TECHNOLOGY_MISMATCH, "An upgrade is available but uses a different install technology than the current installation"),
WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_UPGRADE_INSTALLED_VERSION_MISMATCH, "Installer reported success but the installed version is still older than the upgrade target"),
WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_UPDATE_ALL_HAS_FAILURE, "winget upgrade --all completed with failures"),
WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALLER_SECURITY_CHECK_FAILED, "Installer failed security check"),
WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_DOWNLOAD_SIZE_MISMATCH, "Download size does not match expected content length"),
Expand Down
2 changes: 2 additions & 0 deletions src/AppInstallerSharedLib/Public/AppInstallerErrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@
#define APPINSTALLER_CLI_ERROR_FONT_UNINSTALL_FAILED ((HRESULT)0x8A15008B)
#define APPINSTALLER_CLI_ERROR_FONT_VALIDATION_FAILED ((HRESULT)0x8A15008C)
#define APPINSTALLER_CLI_ERROR_FONT_ROLLBACK_FAILED ((HRESULT)0x8A15008D)
#define APPINSTALLER_CLI_ERROR_UPDATE_INSTALL_TECHNOLOGY_MISMATCH ((HRESULT)0x8A15008E)
#define APPINSTALLER_CLI_ERROR_UPGRADE_INSTALLED_VERSION_MISMATCH ((HRESULT)0x8A15008F)

// Install errors.
#define APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE ((HRESULT)0x8A150101)
Expand Down
4 changes: 4 additions & 0 deletions src/Microsoft.Management.Deployment/Converters.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation
WINGET_GET_OPERATION_RESULT_STATUS(NoApplicableInstallers, InternalError, NoApplicableInstallers, NoApplicableRepairer);
break;
case APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE:
case APPINSTALLER_CLI_ERROR_UPDATE_INSTALL_TECHNOLOGY_MISMATCH:
case APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_UNKNOWN:
case APPINSTALLER_CLI_ERROR_UPGRADE_VERSION_NOT_NEWER:
WINGET_GET_OPERATION_RESULT_STATUS(NoApplicableUpgrade, InternalError, InternalError, InternalError);
Expand All @@ -97,6 +98,9 @@ namespace winrt::Microsoft::Management::Deployment::implementation
case APPINSTALLER_CLI_ERROR_ADMIN_CONTEXT_REPAIR_PROHIBITED:
WINGET_GET_OPERATION_RESULT_STATUS(InternalError, InternalError, InternalError, RepairError);
break;
case APPINSTALLER_CLI_ERROR_UPGRADE_INSTALLED_VERSION_MISMATCH:
WINGET_GET_OPERATION_RESULT_STATUS(InstallError, InternalError, InternalError, InternalError);
break;
case APPINSTALLER_CLI_ERROR_PACKAGE_AGREEMENTS_NOT_ACCEPTED:
WINGET_GET_OPERATION_RESULT_STATUS(PackageAgreementsNotAccepted, InternalError, PackageAgreementsNotAccepted, PackageAgreementsNotAccepted);
break;
Expand Down
Loading