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.