@@ -1929,23 +1929,46 @@ namespace winrt::Microsoft::Windows::Management::Deployment::implementation
1929
1929
errorText.clear ();
1930
1930
activityId = winrt::guid{};
1931
1931
1932
- bool isReady {};
1932
+ winrt::Microsoft::Windows::Management::Deployment::PackageReadyOrNewerAvailableStatus readyOrNewerStatus {};
1933
1933
if (options.RegisterNewerIfAvailable ())
1934
1934
{
1935
1935
// Our caller already verified PackageDeploymentFeature::IsPackageReadyOrNewerAvailable is supported so no need to check again
1936
- isReady = ( IsReadyOrNewerAvailable (packageSetItem) == winrt::Microsoft::Windows::Management::Deployment::PackageReadyOrNewerAvailableStatus::Ready );
1936
+ readyOrNewerStatus = IsReadyOrNewerAvailable (packageSetItem);
1937
1937
}
1938
1938
else
1939
1939
{
1940
- isReady = IsReady (packageSetItem);
1940
+ const bool isReady{ IsReady (packageSetItem) };
1941
+ readyOrNewerStatus = isReady ?
1942
+ winrt::Microsoft::Windows::Management::Deployment::PackageReadyOrNewerAvailableStatus::Ready :
1943
+ winrt::Microsoft::Windows::Management::Deployment::PackageReadyOrNewerAvailableStatus::NotReady;
1941
1944
}
1942
- if (isReady )
1945
+ if (readyOrNewerStatus == winrt::Microsoft::Windows::Management::Deployment::PackageReadyOrNewerAvailableStatus::Ready )
1943
1946
{
1944
1947
return S_OK;
1945
1948
}
1946
1949
1947
- winrt::Windows::Management::Deployment::AddPackageOptions addOptions{ ToOptions (options) };
1950
+ // If the package family's known but a newer version's available on the machine than currently registered
1951
+ // to the user we need to register the family to ensure the newer package is used.
1952
+ //
1953
+ // PackageManager.AddPackage.*Async() SHOULD do that but it doesn't. If the user has foo-v2 registered and foo-v3 is staged
1954
+ // on the machine Add(foo-v2) is a NOOP. This does NOT reigster foo-v3 for the user. That'll require an OS change,
1955
+ // 'cause, backwards compatibility (e.g. Register(foo-v2, options.VersionSupercedence=true)).
1956
+ //
1957
+ // https://task.ms/55967280 tracks this workaround registering the package family.
1958
+ // https://task.ms/56383047 tracks enhancing PackageManager.AddPackage*Async() to support options.VersionSupercedence=true
1959
+ // https://task.ms/56385363 tracks revising this code back to PackageManager.AddPackageByUriAsync() once it supports VersionSupercedence=true (https://task.ms/56383047)
1960
+ if (readyOrNewerStatus == winrt::Microsoft::Windows::Management::Deployment::PackageReadyOrNewerAvailableStatus::NewerAvailable)
1961
+ {
1962
+ // We know there's a package registered to the user >=MinVersion AND there's a newer package than that available on the machine (staged, registered to other users, etc)
1963
+ // IOW we want VersionSupercedence behavior and only RegisterPackageByPackageFamilyName() respects VersionSupercedence so let's do it...
1964
+ winrt::Microsoft::Windows::Management::Deployment::RegisterPackageOptions registerOptions{ ToRegisterOptions (options) };
1965
+ RETURN_IF_FAILED (RegisterPackageByPackageFamilyName (packageSetItem.PackageFamilyName (), registerOptions,
1966
+ packageDeploymentProgress, progress, progressMaxPerPackageSetItem, extendedError, errorText, activityId));
1967
+ return S_OK;
1968
+ }
1969
+
1948
1970
const auto progressBefore{ packageDeploymentProgress.Progress };
1971
+ winrt::Windows::Management::Deployment::AddPackageOptions addOptions{ ToOptions (options) };
1949
1972
auto deploymentOperation{ m_packageManager.AddPackageByUriAsync (packageUri, addOptions) };
1950
1973
deploymentOperation.Progress ([&](winrt::Windows::Foundation::IAsyncOperationWithProgress<
1951
1974
winrt::Windows::Management::Deployment::DeploymentResult,
@@ -3391,7 +3414,7 @@ namespace winrt::Microsoft::Windows::Management::Deployment::implementation
3391
3414
if (options.IsExpectedDigestsSupported ())
3392
3415
{
3393
3416
const auto expectedDigests{ options.ExpectedDigests () };
3394
- if (expectedDigests)
3417
+ if (expectedDigests. Size () > 0 )
3395
3418
{
3396
3419
auto toExpectedDigests{ toOptions.ExpectedDigests () };
3397
3420
for (const auto expectedDigest : expectedDigests)
@@ -3446,7 +3469,7 @@ namespace winrt::Microsoft::Windows::Management::Deployment::implementation
3446
3469
if (options.IsExpectedDigestsSupported ())
3447
3470
{
3448
3471
const auto expectedDigests{ options.ExpectedDigests () };
3449
- if (expectedDigests)
3472
+ if (expectedDigests. Size () > 0 )
3450
3473
{
3451
3474
auto toExpectedDigests{ toOptions.ExpectedDigests () };
3452
3475
for (const auto expectedDigest : expectedDigests)
@@ -3490,7 +3513,7 @@ namespace winrt::Microsoft::Windows::Management::Deployment::implementation
3490
3513
if (options.IsExpectedDigestsSupported ())
3491
3514
{
3492
3515
const auto expectedDigests{ options.ExpectedDigests () };
3493
- if (expectedDigests)
3516
+ if (expectedDigests. Size () > 0 )
3494
3517
{
3495
3518
auto toExpectedDigests{ toOptions.ExpectedDigests () };
3496
3519
for (const auto expectedDigest : expectedDigests)
@@ -3575,6 +3598,61 @@ namespace winrt::Microsoft::Windows::Management::Deployment::implementation
3575
3598
return toOptions;
3576
3599
}
3577
3600
3601
+ winrt::Microsoft::Windows::Management::Deployment::RegisterPackageOptions PackageDeploymentManager::ToRegisterOptions (winrt::Microsoft::Windows::Management::Deployment::EnsureReadyOptions const & options) const
3602
+ {
3603
+ winrt::Microsoft::Windows::Management::Deployment::RegisterPackageOptions toOptions;
3604
+ const auto addOptions{ options.AddPackageOptions () };
3605
+
3606
+ // RegisterPackageOptions has no TargetVolume -- no need (the packge is already staged however it's staged on the machine)
3607
+ for (const auto uri : addOptions.DependencyPackageUris ())
3608
+ {
3609
+ toOptions.DependencyPackageUris ().Append (uri);
3610
+ }
3611
+ for (const auto packageFamilyName : addOptions.OptionalPackageFamilyNames ())
3612
+ {
3613
+ toOptions.OptionalPackageFamilyNames ().Append (packageFamilyName);
3614
+ }
3615
+ // RegisterPackageOptions has no OptionalPackageUris -- warn if any as we won't (can't) use them
3616
+ for (const auto uri : addOptions.OptionalPackageUris ())
3617
+ {
3618
+ const auto uriAsString{ uri.ToString () };
3619
+ (void ) LOG_HR_MSG (MDD_E_WINDOWSAPPRUNTIME_PACKAGEMANAGER_WARNING_OPTION_IGNORED, " OptionalPackageUri: %ls" , uriAsString.c_str ());
3620
+ }
3621
+ // RegisterPackageOptions has no RelatedPackageUris -- warn if any as we won't (can't) use them
3622
+ for (const auto uri : addOptions.RelatedPackageUris ())
3623
+ {
3624
+ const auto uriAsString{ uri.ToString () };
3625
+ (void ) LOG_HR_MSG (MDD_E_WINDOWSAPPRUNTIME_PACKAGEMANAGER_WARNING_OPTION_IGNORED, " RelatedPackageUri: %ls" , uriAsString.c_str ());
3626
+ }
3627
+ const auto externalLocationUri{ addOptions.ExternalLocationUri () };
3628
+ if (externalLocationUri)
3629
+ {
3630
+ toOptions.ExternalLocationUri (externalLocationUri);
3631
+ }
3632
+ // RegisterPackageOptions has no StubPackageOption -- no need (the packge is already staged however it's staged on the machine)
3633
+ toOptions.AllowUnsigned (addOptions.AllowUnsigned ());
3634
+ toOptions.DeveloperMode (addOptions.DeveloperMode ());
3635
+ toOptions.ForceAppShutdown (addOptions.ForceAppShutdown ());
3636
+ toOptions.ForceTargetAppShutdown (addOptions.ForceTargetAppShutdown ());
3637
+ toOptions.ForceUpdateFromAnyVersion (addOptions.ForceUpdateFromAnyVersion ());
3638
+ toOptions.InstallAllResources (addOptions.InstallAllResources ());
3639
+ // RegisterPackageOptions has no RequiredContentGroupOnly -- no need (the packge is already staged however it's staged on the machine)
3640
+ // RegisterPackageOptions has no RetainFilesOnFailure -- no need (the packge is already staged however it's staged on the machine)
3641
+ toOptions.StageInPlace (addOptions.StageInPlace ());
3642
+ toOptions.DeferRegistrationWhenPackagesAreInUse (addOptions.DeferRegistrationWhenPackagesAreInUse ());
3643
+ const auto expectedDigests{ addOptions.ExpectedDigests () };
3644
+ if (expectedDigests)
3645
+ {
3646
+ auto toExpectedDigests{ addOptions.ExpectedDigests () };
3647
+ for (const auto expectedDigest : expectedDigests)
3648
+ {
3649
+ toExpectedDigests.Insert (expectedDigest.Key (), expectedDigest.Value ());
3650
+ }
3651
+ }
3652
+ // RegisterPackageOptions has no LimitToExistingPackages -- no need (the packge is already staged however it's staged on the machine)
3653
+ return toOptions;
3654
+ }
3655
+
3578
3656
double PackageDeploymentManager::PercentageToProgress (uint32_t percentage, const double progressMaxPerItem)
3579
3657
{
3580
3658
return (static_cast <double >(percentage) / 100.0 ) * progressMaxPerItem;
0 commit comments