diff --git a/build/NuSpecs/AppxManifest.xml b/build/NuSpecs/AppxManifest.xml index ef35e49436..1d4cf71972 100644 --- a/build/NuSpecs/AppxManifest.xml +++ b/build/NuSpecs/AppxManifest.xml @@ -38,6 +38,7 @@ <ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentManager" ThreadingModel="both" /> <ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentResult" ThreadingModel="both" /> <ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentInitializeOptions" ThreadingModel="both" /> + <ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentRepairOptions" ThreadingModel="both" /> <!-- VersionInfo --> <ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.WindowsAppRuntime.ReleaseInfo" ThreadingModel="both" /> diff --git a/dev/Deployment/Deployment.idl b/dev/Deployment/Deployment.idl index 224147b04c..15b58a6e5b 100644 --- a/dev/Deployment/Deployment.idl +++ b/dev/Deployment/Deployment.idl @@ -3,7 +3,7 @@ namespace Microsoft.Windows.ApplicationModel.WindowsAppRuntime { - [contractversion(3)] + [contractversion(4)] apicontract DeploymentContract{}; /// Represents the current Deployment status of the WindowsAppRuntime @@ -15,7 +15,8 @@ namespace Microsoft.Windows.ApplicationModel.WindowsAppRuntime PackageInstallRequired, PackageInstallFailed, - [contract(DeploymentContract, 3)] + [contract(DeploymentContract, 4)] + PackageRepairRequired, PackageRepairFailed, }; @@ -49,6 +50,22 @@ namespace Microsoft.Windows.ApplicationModel.WindowsAppRuntime Boolean OnErrorShowUI; }; + /// This object is used to specify deployment options to apply when using DeploymentManager's + /// Repair method + [contract(DeploymentContract, 4)] + runtimeclass DeploymentRepairOptions + { + DeploymentRepairOptions(); + + /// Gets or sets a value that indicates whether the processes associated with the + /// WinAppSDK Main and Singleton packages will be shut down forcibly if they are + /// currently in use, when repairing the WindowsAppRuntime. + Boolean ForceDeployment; + + /// If not successful show UI + Boolean OnErrorShowUI; + }; + /// Used to query deployment information for WindowsAppRuntime [contract(DeploymentContract, 1)] static runtimeclass DeploymentManager @@ -70,7 +87,13 @@ namespace Microsoft.Windows.ApplicationModel.WindowsAppRuntime /// Checks the status of the WindowsAppRuntime of the current package and attempts to /// repair already installed WinAppSDK packages. - [contract(DeploymentContract, 3)] + [contract(DeploymentContract, 4)] static DeploymentResult Repair(); + + /// Checks the status of the WindowsAppRuntime of the current package and attempts to + /// repair already installed WinAppSDK packages, while applying the DeploymentRepairOptions + /// passed in. + [contract(DeploymentContract, 4)] + static DeploymentResult Repair(Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentRepairOptions deploymentRepairOptions); }; } diff --git a/dev/Deployment/Deployment.vcxitems b/dev/Deployment/Deployment.vcxitems index 9636a5884f..639c34ed1f 100644 --- a/dev/Deployment/Deployment.vcxitems +++ b/dev/Deployment/Deployment.vcxitems @@ -21,6 +21,7 @@ <Midl Include="$(MSBuildThisFileDirectory)Deployment.idl" /> </ItemGroup> <ItemGroup> + <ClInclude Include="$(MSBuildThisFileDirectory)DeploymentRepairOptions.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)DeploymentTraceLogging.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)DeploymentInitializeOptions.h" /> <ClInclude Include="$(MSBuildThisFileDirectory)DeploymentManager.h" /> @@ -29,6 +30,7 @@ <ClInclude Include="$(MSBuildThisFileDirectory)PackageDefinitions.h" /> </ItemGroup> <ItemGroup> + <ClCompile Include="$(MSBuildThisFileDirectory)DeploymentRepairOptions.cpp" /> <ClCompile Include="$(MSBuildThisFileDirectory)DeploymentTraceLogging.cpp" /> <ClCompile Include="$(MSBuildThisFileDirectory)DeploymentInitializeOptions.cpp" /> <ClCompile Include="$(MSBuildThisFileDirectory)DeploymentManager.cpp" /> diff --git a/dev/Deployment/DeploymentManager.cpp b/dev/Deployment/DeploymentManager.cpp index 0da7450600..212c441332 100644 --- a/dev/Deployment/DeploymentManager.cpp +++ b/dev/Deployment/DeploymentManager.cpp @@ -6,6 +6,7 @@ #include <DeploymentResult.h> #include <DeploymentActivityContext.h> #include <PackageInfo.h> +#include <AppModel.Package.h> #include <TerminalVelocityFeatures-DeploymentAPI.h> #include <Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentManager.g.cpp> #include <PushNotificationsLongRunningPlatform-Startup.h> @@ -69,10 +70,16 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::DeploymentResult DeploymentManager::Repair() { - winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::DeploymentInitializeOptions options{}; + winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::DeploymentRepairOptions options{}; return Initialize(GetCurrentFrameworkPackageFullName(), options, true); } + winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::DeploymentResult DeploymentManager::Repair( + winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::DeploymentRepairOptions const& deploymentRepairOptions) + { + return Initialize(GetCurrentFrameworkPackageFullName(), deploymentRepairOptions, true); + } + winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::DeploymentResult DeploymentManager::GetStatus(hstring const& packageFullName) { // Get PackageInfo for WinAppSDK framework package @@ -159,11 +166,14 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem return DeploymentManager::Initialize(packageFullName, deploymentInitializeOptions); } + template <typename Options> winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::DeploymentResult DeploymentManager::Initialize( - hstring const& packageFullName, - winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::DeploymentInitializeOptions const& deploymentInitializeOptions, - bool isRepair) + hstring const& packageFullName, Options const& options, bool isRepair) { + THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_DATATYPE), + (!isRepair && typeid(options).name() != typeid(DeploymentInitializeOptions).name()) || + (isRepair && typeid(options).name() != typeid(DeploymentRepairOptions).name())); + auto& initializeActivityContext{ ::WindowsAppRuntime::Deployment::Activity::Context::Get() }; const bool isPackagedProcess{ AppModel::Identity::IsPackagedProcess() }; const int integrityLevel = Security::IntegrityLevel::GetIntegrityLevel(); @@ -173,7 +183,7 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem } ::WindowsAppRuntime::Deployment::Activity::Context::Get().SetIsFullTrustPackage(); - initializeActivityContext.GetActivity().Start(deploymentInitializeOptions.ForceDeployment(), + initializeActivityContext.GetActivity().Start(options.ForceDeployment(), Security::IntegrityLevel::IsElevated(), isPackagedProcess, initializeActivityContext.GetIsFullTrustPackage(), @@ -192,7 +202,7 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem try { - deploymentResult = _Initialize(initializeActivityContext, packageFullName, deploymentInitializeOptions, isRepair); + deploymentResult = _Initialize(initializeActivityContext, packageFullName, options, isRepair); } catch (winrt::hresult_error const& e) { @@ -221,7 +231,7 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem DebugBreak(); } - if (deploymentInitializeOptions.OnErrorShowUI() || + if (options.OnErrorShowUI() || ::Microsoft::Configuration::IsOptionEnabled(L"MICROSOFT_WINDOWSAPPRUNTIME_DEPLOYMENT_INITIALIZE_ONERRORSHOWUI")) { LOG_IF_FAILED(Initialize_OnError_ShowUI(packageIdentity, release)); @@ -234,10 +244,11 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem return deploymentResult; } + template <typename Options> winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::DeploymentResult DeploymentManager::_Initialize( ::WindowsAppRuntime::Deployment::Activity::Context& initializeActivityContext, hstring const& packageFullName, - winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::DeploymentInitializeOptions const& deploymentInitializeOptions, + Options const& options, bool isRepair) { auto getStatusResult{ DeploymentManager::GetStatus(packageFullName) }; @@ -251,7 +262,7 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem } std::wstring frameworkPackageFullName{ packageFullName }; - auto deployPackagesResult{ Deploy(frameworkPackageFullName, deploymentInitializeOptions.ForceDeployment()) }; + auto deployPackagesResult{ Deploy(frameworkPackageFullName, options.ForceDeployment()) }; DeploymentStatus status{}; if (SUCCEEDED(deployPackagesResult)) { @@ -295,61 +306,40 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem return MddCore::PackageInfo::FromPackageInfoReference(packageInfoReference.get()); } - // Borrowed and repurposed from Dynamic Dependencies - std::vector<std::wstring> DeploymentManager::FindPackagesByFamily(std::wstring const& packageFamilyName) - { - UINT32 count{}; - UINT32 bufferLength{}; - const auto rc{ FindPackagesByPackageFamily(packageFamilyName.c_str(), PACKAGE_FILTER_HEAD | PACKAGE_FILTER_DIRECT, &count, nullptr, &bufferLength, nullptr, nullptr) }; - if (rc == ERROR_SUCCESS) - { - // The package family has no packages registered to the user - return std::vector<std::wstring>(); - } - else if (rc != ERROR_INSUFFICIENT_BUFFER) - { - THROW_WIN32(rc); - } - - auto packageFullNames{ wil::make_unique_cotaskmem<PWSTR[]>(count) }; - auto buffer{ wil::make_unique_cotaskmem<WCHAR[]>(bufferLength) }; - THROW_IF_WIN32_ERROR(FindPackagesByPackageFamily(packageFamilyName.c_str(), PACKAGE_FILTER_HEAD | PACKAGE_FILTER_DIRECT, &count, packageFullNames.get(), &bufferLength, buffer.get(), nullptr)); - - std::vector<std::wstring> packageFullNamesList; - for (UINT32 index=0; index < count; ++index) - { - const auto packageFullName{ packageFullNames[index] }; - packageFullNamesList.push_back(std::wstring(packageFullName)); - } - return packageFullNamesList; - } - HRESULT DeploymentManager::VerifyPackage(const std::wstring& packageFamilyName, const PACKAGE_VERSION targetVersion, __out std::wstring& packageIdentifier) try { - auto packageFullNames{ FindPackagesByFamily(packageFamilyName) }; + winrt::Windows::Management::Deployment::PackageManager packageManager; + auto packages{ packageManager.FindPackagesForUserWithPackageTypes(L"", packageFamilyName, + ::Windows::Management::Deployment::PackageTypes::Framework | + ::Windows::Management::Deployment::PackageTypes::Main) }; + bool match{}; - for (const auto& packageFullName : packageFullNames) + bool matchedPackageStatusIsOK{}; + for (const auto& package : packages) { - auto packagePath{ GetPackagePath(packageFullName) }; + auto packagePath{ package.EffectivePath()}; if (packagePath.empty()) { continue; } - auto packageId{ AppModel::Identity::PackageIdentity::FromPackageFullName(packageFullName.c_str()) }; - if (packageId.Version().Version >= targetVersion.Version) + const auto packageVersion{ AppModel::Package::ToPackageVersion(package.Id().Version()).Version }; + + if (packageVersion >= targetVersion.Version) { match = true; - if (packageId.Version().Version > targetVersion.Version) + matchedPackageStatusIsOK = package.Status().VerifyIsOK(); + if (packageVersion > targetVersion.Version) { - g_existingTargetPackagesIfHigherVersion.insert(std::make_pair(packageIdentifier, packageFullName)); + g_existingTargetPackagesIfHigherVersion.insert(std::make_pair(packageIdentifier, package.Id().FullName())); } break; } } RETURN_HR_IF(HRESULT_FROM_WIN32(ERROR_NOT_FOUND), !match); + RETURN_HR_IF(HRESULT_FROM_WIN32(ERROR_INVALID_STATE), !matchedPackageStatusIsOK); return S_OK; } CATCH_RETURN() diff --git a/dev/Deployment/DeploymentManager.h b/dev/Deployment/DeploymentManager.h index 2129270aa3..333cb0f4fc 100644 --- a/dev/Deployment/DeploymentManager.h +++ b/dev/Deployment/DeploymentManager.h @@ -19,19 +19,20 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem static WindowsAppRuntime::DeploymentResult Initialize(); static WindowsAppRuntime::DeploymentResult Initialize(WindowsAppRuntime::DeploymentInitializeOptions const& deploymentInitializeOptions); static WindowsAppRuntime::DeploymentResult Repair(); + static WindowsAppRuntime::DeploymentResult Repair(WindowsAppRuntime::DeploymentRepairOptions const& deploymentRepairOptions); private: static WindowsAppRuntime::DeploymentResult GetStatus(hstring const& packageFullName); static WindowsAppRuntime::DeploymentResult Initialize(hstring const& packageFullName); - static WindowsAppRuntime::DeploymentResult Initialize(hstring const& packageFullName, - WindowsAppRuntime::DeploymentInitializeOptions const& deploymentInitializeOptions, - bool isRepair = false); + template <typename Options> + static WindowsAppRuntime::DeploymentResult Initialize(hstring const& packageFullName, Options const& tOoptions, bool isRepair = false); private: + template <typename Options> static WindowsAppRuntime::DeploymentResult _Initialize( ::WindowsAppRuntime::Deployment::Activity::Context& initializeActivityContext, hstring const& packageFullName, - WindowsAppRuntime::DeploymentInitializeOptions const& deploymentInitializeOptions, + Options const& tOoptions, bool isRepair); private: diff --git a/dev/Deployment/DeploymentRepairOptions.cpp b/dev/Deployment/DeploymentRepairOptions.cpp new file mode 100644 index 0000000000..cfacc09116 --- /dev/null +++ b/dev/Deployment/DeploymentRepairOptions.cpp @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. +#include <pch.h> +#include <DeploymentRepairOptions.h> +#include <Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentRepairOptions.g.cpp> + +namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implementation +{ + bool DeploymentRepairOptions::ForceDeployment() + { + return m_ForceDeployment; + } + void DeploymentRepairOptions::ForceDeployment(bool value) + { + m_ForceDeployment = value; + } + bool DeploymentRepairOptions::OnErrorShowUI() + { + return m_OnErrorShowUI; + } + void DeploymentRepairOptions::OnErrorShowUI(bool value) + { + m_OnErrorShowUI = value; + } +} diff --git a/dev/Deployment/DeploymentRepairOptions.h b/dev/Deployment/DeploymentRepairOptions.h new file mode 100644 index 0000000000..526d9f304f --- /dev/null +++ b/dev/Deployment/DeploymentRepairOptions.h @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation and Contributors. +// Licensed under the MIT License. + +#pragma once + +#include "Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentRepairOptions.g.h" + +namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implementation +{ + struct DeploymentRepairOptions : DeploymentRepairOptionsT<DeploymentRepairOptions> + { + DeploymentRepairOptions() = default; + + bool ForceDeployment(); + void ForceDeployment(bool value); + bool OnErrorShowUI(); + void OnErrorShowUI(bool value); + + private: + bool m_ForceDeployment{}; + bool m_OnErrorShowUI{}; + }; +} +namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::factory_implementation +{ + struct DeploymentRepairOptions : DeploymentRepairOptionsT<DeploymentRepairOptions, implementation::DeploymentRepairOptions> + { + }; +} diff --git a/test/Deployment/data/WindowsAppRuntime.Test.Framework/appxmanifest.xml b/test/Deployment/data/WindowsAppRuntime.Test.Framework/appxmanifest.xml index a3c742d4a2..1ef24f980b 100644 --- a/test/Deployment/data/WindowsAppRuntime.Test.Framework/appxmanifest.xml +++ b/test/Deployment/data/WindowsAppRuntime.Test.Framework/appxmanifest.xml @@ -50,6 +50,7 @@ <ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentManager" ThreadingModel="both" /> <ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentResult" ThreadingModel="both" /> <ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentInitializeOptions" ThreadingModel="both" /> + <ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentRepairOptions" ThreadingModel="both" /> </InProcessServer> </Extension> <Extension Category="windows.activatableClass.inProcessServer"> diff --git a/test/DynamicDependency/data/Microsoft.WindowsAppRuntime.Framework/appxmanifest.xml b/test/DynamicDependency/data/Microsoft.WindowsAppRuntime.Framework/appxmanifest.xml index fecee5598d..99ca9bb4a8 100644 --- a/test/DynamicDependency/data/Microsoft.WindowsAppRuntime.Framework/appxmanifest.xml +++ b/test/DynamicDependency/data/Microsoft.WindowsAppRuntime.Framework/appxmanifest.xml @@ -50,6 +50,7 @@ <ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentManager" ThreadingModel="both" /> <ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentResult" ThreadingModel="both" /> <ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentInitializeOptions" ThreadingModel="both" /> + <ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.WindowsAppRuntime.DeploymentRepairOptions" ThreadingModel="both" /> </InProcessServer> </Extension> <Extension Category="windows.activatableClass.inProcessServer">