diff --git a/doc/windows/package-manager/winget/returnCodes.md b/doc/windows/package-manager/winget/returnCodes.md
index 1ec122dcef..2b59deca7d 100644
--- a/doc/windows/package-manager/winget/returnCodes.md
+++ b/doc/windows/package-manager/winget/returnCodes.md
@@ -153,6 +153,7 @@ 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 |
## Install errors.
diff --git a/src/AppInstallerCLICore/Resources.h b/src/AppInstallerCLICore/Resources.h
index ef3db8b395..11b4b8d1a7 100644
--- a/src/AppInstallerCLICore/Resources.h
+++ b/src/AppInstallerCLICore/Resources.h
@@ -796,6 +796,7 @@ 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(UpgradeIsPinned);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradePinnedByUserCount);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeRequireExplicitCount);
diff --git a/src/AppInstallerCLICore/Workflows/UpdateFlow.cpp b/src/AppInstallerCLICore/Workflows/UpdateFlow.cpp
index a873e15b3b..fbdeddfb76 100644
--- a/src/AppInstallerCLICore/Workflows/UpdateFlow.cpp
+++ b/src/AppInstallerCLICore/Workflows/UpdateFlow.cpp
@@ -186,6 +186,10 @@ namespace AppInstaller::CLI::Workflow
context.Reporter.Error() << Resource::String::NoApplicableInstallers << std::endl;
}
}
+ if (isUpgrade && installedTypeInapplicable)
+ {
+ AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_UPDATE_INSTALL_TECHNOLOGY_MISMATCH);
+ }
AICLI_TERMINATE_CONTEXT(isUpgrade ? APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE : APPINSTALLER_CLI_ERROR_NO_APPLICABLE_INSTALLER);
}
@@ -212,6 +216,7 @@ namespace AppInstaller::CLI::Workflow
bool updateAllFoundUpdate = false;
int packagesWithUnknownVersionSkipped = 0;
int packagesThatRequireExplicitSkipped = 0;
+ int packagesSkippedInstallTechnologyMismatch = 0;
for (const auto& match : matches)
{
@@ -238,6 +243,14 @@ namespace AppInstaller::CLI::Workflow
Workflow::ReportExecutionStage(ExecutionStage::Discovery) <<
SelectLatestApplicableVersion(false);
+ if (updateContext.GetTerminationHR() == APPINSTALLER_CLI_ERROR_UPDATE_INSTALL_TECHNOLOGY_MISMATCH)
+ {
+ AICLI_LOG(CLI, Info, << "Skipping " << match.Package->GetProperty(PackageProperty::Id)
+ << " as available upgrades use a different install technology");
+ ++packagesSkippedInstallTechnologyMismatch;
+ continue;
+ }
+
if (updateContext.GetTerminationHR() == APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE)
{
continue;
@@ -295,6 +308,12 @@ namespace AppInstaller::CLI::Workflow
AICLI_LOG(CLI, Info, << packagesThatRequireExplicitSkipped << " package(s) skipped due to requiring explicit upgrade");
context.Reporter.Info() << Resource::String::UpgradeRequireExplicitCount(packagesThatRequireExplicitSkipped) << std::endl;
}
+
+ if (packagesSkippedInstallTechnologyMismatch > 0)
+ {
+ AICLI_LOG(CLI, Info, << packagesSkippedInstallTechnologyMismatch << " package(s) skipped due to install technology mismatch");
+ context.Reporter.Info() << Resource::String::UpgradeInstallTechnologyMismatchCount(packagesSkippedInstallTechnologyMismatch) << std::endl;
+ }
}
void SelectSinglePackageVersionForInstallOrUpgrade::operator()(Execution::Context& context) const
diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw
index 6cfee598b7..64fc8df0fb 100644
--- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw
+++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw
@@ -1345,6 +1345,10 @@ Please specify one of them using the --source option to proceed.
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.
+
+ {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.
+ {Locked="{0}"} {0} is the number of packages skipped for this reason during winget upgrade --all.
+
The install technology of the newer version specified is different from the current version installed. Please uninstall the package and install the newer version.
@@ -2265,6 +2269,9 @@ Please specify one of them using the --source option to proceed.
No applicable update found
+
+ An upgrade is available but uses a different install technology than the current installation
+
winget upgrade --all completed with failures
diff --git a/src/AppInstallerCLITests/UpdateFlow.cpp b/src/AppInstallerCLITests/UpdateFlow.cpp
index 7c9ddb8602..6e38204bb2 100644
--- a/src/AppInstallerCLITests/UpdateFlow.cpp
+++ b/src/AppInstallerCLITests/UpdateFlow.cpp
@@ -429,7 +429,7 @@ TEST_CASE("UpdateFlow_UpdateExeInstallerTypeNotApplicable", "[UpdateFlow][workfl
// Verify Installer is not called.
REQUIRE(!std::filesystem::exists(updateResultPath.GetPath()));
REQUIRE(updateOutput.str().find(Resource::LocString(Resource::String::UpgradeDifferentInstallTechnologyInNewerVersions).get()) != std::string::npos);
- REQUIRE(context.GetTerminationHR() == APPINSTALLER_CLI_ERROR_UPDATE_NOT_APPLICABLE);
+ REQUIRE(context.GetTerminationHR() == APPINSTALLER_CLI_ERROR_UPDATE_INSTALL_TECHNOLOGY_MISMATCH);
}
TEST_CASE("UpdateFlow_UpdateExeInstallerTypeNotApplicableSpecificVersion", "[UpdateFlow][workflow]")
diff --git a/src/AppInstallerSharedLib/Errors.cpp b/src/AppInstallerSharedLib/Errors.cpp
index e3fdd13f1d..20414f6b75 100644
--- a/src/AppInstallerSharedLib/Errors.cpp
+++ b/src/AppInstallerSharedLib/Errors.cpp
@@ -131,6 +131,7 @@ 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_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"),
diff --git a/src/AppInstallerSharedLib/Public/AppInstallerErrors.h b/src/AppInstallerSharedLib/Public/AppInstallerErrors.h
index 2bb4ad097e..a8bfdf40da 100644
--- a/src/AppInstallerSharedLib/Public/AppInstallerErrors.h
+++ b/src/AppInstallerSharedLib/Public/AppInstallerErrors.h
@@ -162,6 +162,7 @@
#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)
// Install errors.
#define APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE ((HRESULT)0x8A150101)
diff --git a/src/Microsoft.Management.Deployment/Converters.h b/src/Microsoft.Management.Deployment/Converters.h
index 460fe4e21c..643658705c 100644
--- a/src/Microsoft.Management.Deployment/Converters.h
+++ b/src/Microsoft.Management.Deployment/Converters.h
@@ -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);