diff --git a/WindowsAppRuntime.sln b/WindowsAppRuntime.sln
index 4ef85a6761..fb2adede2a 100644
--- a/WindowsAppRuntime.sln
+++ b/WindowsAppRuntime.sln
@@ -750,6 +750,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StoragePickers", "StoragePi
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Deployment.WindowsAppRuntime.Test.SingletonHigherVersion", "test\Deployment\data\WindowsAppRuntime.Test.SingletonHigherVersion\WindowsAppRuntime.Test.SingletonHigherVersion.vcxproj", "{462CF10A-E6B5-4005-8E25-132D1DE589B7}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Deployment.WindowsAppRuntime.Test.SingletonLowerVersion", "test\Deployment\data\WindowsAppRuntime.Test.SingletonLowerVersion\WindowsAppRuntime.Test.SingletonLowerVersion.vcxproj", "{7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -2644,6 +2646,22 @@ Global
{462CF10A-E6B5-4005-8E25-132D1DE589B7}.Release|x64.Build.0 = Release|x64
{462CF10A-E6B5-4005-8E25-132D1DE589B7}.Release|x86.ActiveCfg = Release|Win32
{462CF10A-E6B5-4005-8E25-132D1DE589B7}.Release|x86.Build.0 = Release|Win32
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Debug|Any CPU.Build.0 = Debug|x64
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Debug|ARM64.Build.0 = Debug|ARM64
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Debug|x64.ActiveCfg = Debug|x64
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Debug|x64.Build.0 = Debug|x64
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Debug|x86.ActiveCfg = Debug|Win32
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Debug|x86.Build.0 = Debug|Win32
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Release|Any CPU.ActiveCfg = Release|x64
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Release|Any CPU.Build.0 = Release|x64
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Release|ARM64.ActiveCfg = Release|ARM64
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Release|ARM64.Build.0 = Release|ARM64
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Release|x64.ActiveCfg = Release|x64
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Release|x64.Build.0 = Release|x64
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Release|x86.ActiveCfg = Release|Win32
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2871,6 +2889,7 @@ Global
{346E099B-45E4-FF40-E63D-8B34915223C1} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D}
{06AA7FD7-36BE-41AC-9008-56919D1612C6} = {3B706C5C-55E0-4B76-BF59-89E20FE46795}
{462CF10A-E6B5-4005-8E25-132D1DE589B7} = {2B653A15-2482-40E5-9509-C531E69D0749}
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D} = {2B653A15-2482-40E5-9509-C531E69D0749}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4B3D7591-CFEC-4762-9A07-ABE99938FB77}
diff --git a/dev/Deployment/DeploymentManager.cpp b/dev/Deployment/DeploymentManager.cpp
index 8024391606..a342ad5757 100644
--- a/dev/Deployment/DeploymentManager.cpp
+++ b/dev/Deployment/DeploymentManager.cpp
@@ -368,7 +368,8 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem
const std::wstring& packageIdentifier) try
{
auto packageFullNames{ FindPackagesByFamily(packageFamilyName) };
- bool match{};
+ UINT64 highestVersionFound{ 0 }; // There is no package with version 0
+ std::wstring highestVersionPackageFullName{};
for (const auto& packageFullName : packageFullNames)
{
auto packagePath{ GetPackagePath(packageFullName) };
@@ -378,18 +379,20 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem
}
auto packageId{ AppModel::Identity::PackageIdentity::FromPackageFullName(packageFullName.c_str()) };
- if (packageId.Version().Version >= targetVersion.Version)
+ const auto packageVersion{ packageId.Version().Version };
+ if (packageVersion > highestVersionFound)
{
- match = true;
- if (packageId.Version().Version > targetVersion.Version)
- {
- g_existingTargetPackagesIfHigherVersion.insert(std::make_pair(packageIdentifier, packageFullName));
- }
- break;
+ highestVersionFound = packageVersion;
+ highestVersionPackageFullName = packageFullName;
}
}
- RETURN_HR_IF(HRESULT_FROM_WIN32(ERROR_NOT_FOUND), !match);
+ if (highestVersionFound > targetVersion.Version)
+ {
+ g_existingTargetPackagesIfHigherVersion[packageIdentifier] = highestVersionPackageFullName;
+ }
+
+ RETURN_HR_IF(HRESULT_FROM_WIN32(ERROR_NOT_FOUND), highestVersionFound < targetVersion.Version);
return S_OK;
}
CATCH_RETURN()
diff --git a/test/Deployment/API/APITests.cpp b/test/Deployment/API/APITests.cpp
index 2c6d094446..b205dbbdcd 100644
--- a/test/Deployment/API/APITests.cpp
+++ b/test/Deployment/API/APITests.cpp
@@ -41,6 +41,7 @@ namespace Test::Deployment
{
TP::RemovePackage_DeploymentWindowsAppRuntimeSingletonHigherVersion();
TP::RemovePackage_DeploymentWindowsAppRuntimeSingleton();
+ TP::RemovePackage_DeploymentWindowsAppRuntimeSingletonLowerVersion();
TP::RemovePackage_DeploymentWindowsAppRuntimeMain();
TP::RemovePackage_DeploymentWindowsAppRuntimeFramework();
TP::RemovePackage_WindowsAppRuntimeFramework();
@@ -190,6 +191,36 @@ namespace Test::Deployment
return;
}
+ TEST_METHOD(Initialize_LowerSingletonVersionPresent)
+ {
+ BEGIN_TEST_METHOD_PROPERTIES()
+ TEST_METHOD_PROPERTY(L"RunAs", L"UAP")
+ TEST_METHOD_PROPERTY(L"UAP:AppxManifest", L"Deployment-Capabilities-AppxManifest.xml")
+ END_TEST_METHOD_PROPERTIES();
+
+ // Add only the lower version singleton package externally to the API (e.g. the installer).
+ TP::AddPackage_DeploymentWindowsAppRuntimeSingletonLowerVersion();
+ VERIFY_IS_TRUE(TP::IsPackageRegistered_DeploymentWindowsAppRuntimeSingletonLowerVersion());
+
+ // Verify package status is by default not OK.
+ auto result{ DeploymentManager::GetStatus() };
+ Log::Comment(WEX::Common::String().Format(L"Status: 0x%0X", result.ExtendedError().value));
+ VERIFY_IS_TRUE(result.Status() == DeploymentStatus::PackageInstallRequired);
+
+ // Call Initialize to correct and check status again.
+ result = DeploymentManager::Initialize();
+ Log::Comment(WEX::Common::String().Format(L"Initialize: 0x%0X", result.ExtendedError().value));
+ VERIFY_IS_TRUE(result.Status() == DeploymentStatus::Ok);
+
+ result = DeploymentManager::GetStatus();
+ Log::Comment(WEX::Common::String().Format(L"Status: 0x%0X", result.ExtendedError().value));
+ VERIFY_IS_TRUE(result.Status() == DeploymentStatus::Ok);
+
+ VERIFY_IS_FALSE(TP::IsPackageRegistered_DeploymentWindowsAppRuntimeSingletonLowerVersion());
+ VERIFY_IS_TRUE(TP::IsPackageRegistered_DeploymentWindowsAppRuntimeSingleton());
+ return;
+ }
+
TEST_METHOD(Initialize_HigherSingletonVersionPresent)
{
BEGIN_TEST_METHOD_PROPERTIES()
@@ -214,6 +245,33 @@ namespace Test::Deployment
return;
}
+ TEST_METHOD(Initialize_MultipleVersionPresent_GetsHighest)
+ {
+ BEGIN_TEST_METHOD_PROPERTIES()
+ TEST_METHOD_PROPERTY(L"RunAs", L"UAP")
+ TEST_METHOD_PROPERTY(L"UAP:AppxManifest", L"Deployment-Capabilities-AppxManifest.xml")
+ END_TEST_METHOD_PROPERTIES();
+
+ // Add both the lower and higher version singleton packages externally to the API (e.g. the installer).
+ TP::AddPackage_DeploymentWindowsAppRuntimeSingletonLowerVersion();
+ TP::AddPackage_DeploymentWindowsAppRuntimeSingleton();
+ TP::AddPackage_DeploymentWindowsAppRuntimeSingletonHigherVersion();
+
+ // Call Initialize to correct and check status again.
+ auto result = DeploymentManager::Initialize();
+ Log::Comment(WEX::Common::String().Format(L"Initialize: 0x%0X", result.ExtendedError().value));
+ VERIFY_IS_TRUE(result.Status() == DeploymentStatus::Ok);
+
+ result = DeploymentManager::GetStatus();
+ Log::Comment(WEX::Common::String().Format(L"Status: 0x%0X", result.ExtendedError().value));
+ VERIFY_IS_TRUE(result.Status() == DeploymentStatus::Ok);
+
+ VERIFY_IS_FALSE(TP::IsPackageRegistered_DeploymentWindowsAppRuntimeSingletonLowerVersion());
+ VERIFY_IS_FALSE(TP::IsPackageRegistered_DeploymentWindowsAppRuntimeSingleton());
+ VERIFY_IS_TRUE(TP::IsPackageRegistered_DeploymentWindowsAppRuntimeSingletonHigherVersion());
+ return;
+ }
+
TEST_METHOD(Initialize_NoCapabilities)
{
BEGIN_TEST_METHOD_PROPERTIES()
diff --git a/test/Deployment/API/DeploymentTests.vcxproj b/test/Deployment/API/DeploymentTests.vcxproj
index fd602d5c97..706f411c26 100644
--- a/test/Deployment/API/DeploymentTests.vcxproj
+++ b/test/Deployment/API/DeploymentTests.vcxproj
@@ -225,6 +225,9 @@
{462cf10a-e6b5-4005-8e25-132d1de589b7}
+
+ {7a3c8f5d-9b2e-4a1f-8d6c-3e9f7b4a2c1d}
+
diff --git a/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/Assets/SplashScreen.png b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/Assets/SplashScreen.png
new file mode 100644
index 0000000000..c0ab709dc6
Binary files /dev/null and b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/Assets/SplashScreen.png differ
diff --git a/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/Assets/Square150x150Logo.png b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/Assets/Square150x150Logo.png
new file mode 100644
index 0000000000..9a071d26df
Binary files /dev/null and b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/Assets/Square150x150Logo.png differ
diff --git a/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/Assets/Square44x44Logo.png b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/Assets/Square44x44Logo.png
new file mode 100644
index 0000000000..4af71543c6
Binary files /dev/null and b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/Assets/Square44x44Logo.png differ
diff --git a/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/Assets/Wide310x150Logo.png b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/Assets/Wide310x150Logo.png
new file mode 100644
index 0000000000..58f66a369f
Binary files /dev/null and b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/Assets/Wide310x150Logo.png differ
diff --git a/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/Assets/logo.png b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/Assets/logo.png
new file mode 100644
index 0000000000..0c4cc6ca77
Binary files /dev/null and b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/Assets/logo.png differ
diff --git a/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/WindowsAppRuntime.Test.SingletonLowerVersion.vcxproj b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/WindowsAppRuntime.Test.SingletonLowerVersion.vcxproj
new file mode 100644
index 0000000000..bce6a08e03
--- /dev/null
+++ b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/WindowsAppRuntime.Test.SingletonLowerVersion.vcxproj
@@ -0,0 +1,113 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Release
+ ARM64
+
+
+
+ 16.0
+ {7A3C8F5D-9B2E-4A1F-8D6C-3E9F7B4A2C1D}
+ Win32Proj
+ Deployment.WindowsAppRuntime.Test.SingletonLowerVersion
+
+
+
+ Makefile
+ true
+ v143
+
+
+ Makefile
+ false
+ v143
+
+
+ Makefile
+ true
+ v143
+
+
+ Makefile
+ false
+ v143
+
+
+ Makefile
+ true
+ v143
+
+
+ Makefile
+ false
+ v143
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(PostBuildDependsOn);MakeMSIX
+ REM Nothing to do!
+ REM TODO Clean then Build
+ REM TODO Clean
+
+ Deployment.WindowsAppRuntime.Test.SingletonLowerVersion.msix
+
+
+
+
+
+
+ $(RepoTestCertificatePFX)
+ $(RepoTestCertificatePassword)
+
+
+
+
+
+
+
+
+
diff --git a/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/WindowsAppRuntime.Test.SingletonLowerVersion.vcxproj.filters b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/WindowsAppRuntime.Test.SingletonLowerVersion.vcxproj.filters
new file mode 100644
index 0000000000..70ba67fcde
--- /dev/null
+++ b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/WindowsAppRuntime.Test.SingletonLowerVersion.vcxproj.filters
@@ -0,0 +1,23 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+
+
+
+
+
diff --git a/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/appxmanifest.xml b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/appxmanifest.xml
new file mode 100644
index 0000000000..190b90ed86
--- /dev/null
+++ b/test/Deployment/data/WindowsAppRuntime.Test.SingletonLowerVersion/appxmanifest.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+ MicrosoftCorporationII.WinAppRuntime.Singleton.Test (aka Microsoft.WindowsAppRuntime.Singleton) fake for tests
+ Microsoft Corporation
+ Assets\logo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/inc/WindowsAppRuntime.Test.Package.h b/test/inc/WindowsAppRuntime.Test.Package.h
index 2615b07975..5c1bb8de6b 100644
--- a/test/inc/WindowsAppRuntime.Test.Package.h
+++ b/test/inc/WindowsAppRuntime.Test.Package.h
@@ -134,6 +134,13 @@ namespace DeploymentWindowsAppRuntimeSingletonHigherVersion
constexpr PCWSTR c_PackageFullName = WINDOWSAPPRUNTIME_TEST_MSIX_DEPLOYMENT_SINGLETON_PACKAGE_NAME L"_4.1.1968.333_neutral__" WINDOWSAPPRUNTIME_TEST_MSIX_PUBLISHERID;
}
+namespace DeploymentWindowsAppRuntimeSingletonLowerVersion
+{
+ constexpr PCWSTR c_PackageDirName = L"Deployment.WindowsAppRuntime.Test.SingletonLowerVersion";
+ constexpr PCWSTR c_PackageFamilyName = WINDOWSAPPRUNTIME_TEST_MSIX_DEPLOYMENT_SINGLETON_PACKAGE_NAME L"_" WINDOWSAPPRUNTIME_TEST_MSIX_PUBLISHERID;
+ constexpr PCWSTR c_PackageFullName = WINDOWSAPPRUNTIME_TEST_MSIX_DEPLOYMENT_SINGLETON_PACKAGE_NAME L"_4.1.1966.333_neutral__" WINDOWSAPPRUNTIME_TEST_MSIX_PUBLISHERID;
+}
+
template
inline T GetPackagePath(PCWSTR packageFullName)
{
@@ -640,6 +647,27 @@ inline bool IsPackageRegistered_DeploymentWindowsAppRuntimeSingletonHigherVersio
return IsPackageRegistered(Test::Packages::DeploymentWindowsAppRuntimeSingletonHigherVersion::c_PackageFullName);
}
+inline void AddPackage_DeploymentWindowsAppRuntimeSingletonLowerVersion()
+{
+ AddPackage(Test::Packages::DeploymentWindowsAppRuntimeSingletonLowerVersion::c_PackageDirName, Test::Packages::DeploymentWindowsAppRuntimeSingletonLowerVersion::c_PackageFullName);
+}
+
+inline void RemovePackage_DeploymentWindowsAppRuntimeSingletonLowerVersion()
+{
+ // Best-effort removal. PackageManager.RemovePackage errors if the package
+ // is not registered, but if it's not registered we're good. "'Tis the destination
+ // that matters, not the journey" so regardless how much or little work
+ // we need do, we're happy as long as the package isn't registered when we're done
+ //
+ // Thus, do a *IfNecessary removal
+ RemovePackageIfNecessary(Test::Packages::DeploymentWindowsAppRuntimeSingletonLowerVersion::c_PackageFullName);
+}
+
+inline bool IsPackageRegistered_DeploymentWindowsAppRuntimeSingletonLowerVersion()
+{
+ return IsPackageRegistered(Test::Packages::DeploymentWindowsAppRuntimeSingletonLowerVersion::c_PackageFullName);
+}
+
inline std::filesystem::path GetWindowsAppRuntimeFrameworkMsixPath()
{
// Determine the location of the WindowsAppRuntime Framework's msix. See GetSolutionOutDirPath() for more details.