Skip to content

Add DeploymentRepairOptions #3001

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build/NuSpecs/AppxManifest.xml
Original file line number Diff line number Diff line change
@@ -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" />
29 changes: 26 additions & 3 deletions dev/Deployment/Deployment.idl
Original file line number Diff line number Diff line change
@@ -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);
};
}
2 changes: 2 additions & 0 deletions dev/Deployment/Deployment.vcxitems
Original file line number Diff line number Diff line change
@@ -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" />
80 changes: 35 additions & 45 deletions dev/Deployment/DeploymentManager.cpp
Original file line number Diff line number Diff line change
@@ -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()
9 changes: 5 additions & 4 deletions dev/Deployment/DeploymentManager.h
Original file line number Diff line number Diff line change
@@ -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:
25 changes: 25 additions & 0 deletions dev/Deployment/DeploymentRepairOptions.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
}
29 changes: 29 additions & 0 deletions dev/Deployment/DeploymentRepairOptions.h
Original file line number Diff line number Diff line change
@@ -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>
{
};
}
Original file line number Diff line number Diff line change
@@ -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">
Original file line number Diff line number Diff line change
@@ -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">