Skip to content
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

Add DeploymentRepairOptions #3001

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
Expand Up @@ -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" />
Expand Down
29 changes: 26 additions & 3 deletions dev/Deployment/Deployment.idl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Microsoft.Windows.ApplicationModel.WindowsAppRuntime
{
[contractversion(3)]
[contractversion(4)]
apicontract DeploymentContract{};

/// Represents the current Deployment status of the WindowsAppRuntime
Expand All @@ -15,7 +15,8 @@ namespace Microsoft.Windows.ApplicationModel.WindowsAppRuntime
PackageInstallRequired,
PackageInstallFailed,

[contract(DeploymentContract, 3)]
[contract(DeploymentContract, 4)]
PackageRepairRequired,
PackageRepairFailed,
};

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Up @@ -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" />
Expand All @@ -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" />
Expand Down
80 changes: 35 additions & 45 deletions dev/Deployment/DeploymentManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand All @@ -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(),
Expand All @@ -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)
{
Expand Down Expand Up @@ -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));
Expand All @@ -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) };
Expand All @@ -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))
{
Expand Down Expand Up @@ -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()
Expand Down
9 changes: 5 additions & 4 deletions dev/Deployment/DeploymentManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
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
Expand Up @@ -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">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down