Skip to content
Open
Show file tree
Hide file tree
Changes from 57 commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
eba0fc5
fix packageFamilyName
ssparach Aug 20, 2025
62dcc52
fix format
ssparach Aug 20, 2025
a98dcc0
Enabling deployment tests
guimafelipe Aug 26, 2025
3737132
Update DeploymentManager.cpp
ssparach Sep 2, 2025
2b19bb2
Merge branch 'main' into user/ssparach/depMngrFixPackageFamilyName
ssparach Sep 2, 2025
bfeda67
Merge branch 'main' into user/felipeda/deploymenttests
guimafelipe Sep 2, 2025
a96f4b3
Merge branch 'user/ssparach/depMngrFixPackageFamilyName' into user/fe…
guimafelipe Sep 2, 2025
e11fd1c
Fixing packages names
guimafelipe Sep 3, 2025
610cc5c
Deploying agent with package
guimafelipe Sep 4, 2025
6c5e345
Fixing framework package name
guimafelipe Sep 4, 2025
bfbee0f
Fixing framework package name in all tests
guimafelipe Sep 4, 2025
7a19ab5
Fixing applifecycle test app bootstrap initialization
guimafelipe Sep 4, 2025
6c3c31e
Cleanup code
guimafelipe Sep 4, 2025
dd91f1f
Merge branch 'main' into user/felipeda/deploymenttests2
guimafelipe Sep 9, 2025
a1224f2
Merge branch 'main' into user/felipeda/refactordeployment
guimafelipe Sep 16, 2025
b7a33b7
Separating classes
guimafelipe Sep 17, 2025
7476376
Injecting context in install packages
guimafelipe Sep 17, 2025
7aacedc
Injecting path
guimafelipe Sep 17, 2025
69fdaae
Inject package path utilities
guimafelipe Sep 17, 2025
fe992f7
Moving package registration to different class
guimafelipe Sep 17, 2025
2a46465
Injecting stuff into package registar
guimafelipe Sep 18, 2025
a3e442f
Basic test for registrar
guimafelipe Sep 18, 2025
1e11abb
Refactored to namespaces
guimafelipe Sep 18, 2025
2ff61a8
One test running!
guimafelipe Sep 18, 2025
4938912
Filters!
guimafelipe Sep 18, 2025
1c8db29
Removing tests and refactoring
guimafelipe Sep 19, 2025
8612e5f
Separating deploy packages
guimafelipe Sep 19, 2025
4f1ff76
Separating install
guimafelipe Sep 19, 2025
29f25fe
Small refactoring
guimafelipe Sep 19, 2025
b9d2453
Added interface for license installer
guimafelipe Sep 19, 2025
d8d32be
Refactored hard dependencies out of deployer
guimafelipe Sep 19, 2025
4d65049
Unit tests running, not passing
guimafelipe Sep 20, 2025
22740a0
skipping test
guimafelipe Sep 20, 2025
cbc3599
Adding comment
guimafelipe Sep 20, 2025
0154acf
Quick fix
guimafelipe Sep 20, 2025
7c37c84
Converting package path utilities into function instead of object
guimafelipe Sep 21, 2025
c0bc0db
Moving package functions to different namespace
guimafelipe Sep 21, 2025
857b2a4
Renaming package files/namespace and moving more functions to it
guimafelipe Sep 21, 2025
be59d11
Adding testing with mock files
guimafelipe Sep 21, 2025
0c01e83
Adjusting some includes
guimafelipe Sep 21, 2025
4779f01
Passing activity context to deploy as argument
guimafelipe Sep 21, 2025
d00d35a
Adding comment
guimafelipe Sep 21, 2025
0aea9e7
Passing as reference
guimafelipe Sep 21, 2025
d6657c2
Removing default arguments
guimafelipe Sep 21, 2025
f134860
Tweaking tests
guimafelipe Sep 21, 2025
c7cb322
Tweaking tests 2
guimafelipe Sep 22, 2025
fa40aeb
Moving deploy back to manager
guimafelipe Sep 22, 2025
67d3885
Moving back for deploy package and install licenses methods in the ma…
guimafelipe Sep 22, 2025
bbb2177
Merge branch 'main' into user/felipeda/refactordeployment
guimafelipe Sep 22, 2025
bf36c36
Adding failing tests
guimafelipe Sep 22, 2025
28518fb
Reverting vcxproj for original deployment tests
guimafelipe Sep 22, 2025
cc2eb0b
Quick fix 2
guimafelipe Sep 22, 2025
cf992ba
Ignoring failing test
guimafelipe Sep 22, 2025
f75bddf
Adding reset to clear data from install licenses
guimafelipe Sep 24, 2025
f0c3505
Revamping tests
guimafelipe Sep 25, 2025
4d36469
Merge branch 'main' into user/felipeda/refactordeployment
guimafelipe Oct 2, 2025
7dd4c79
Merge branch 'main' into user/felipeda/refactordeployment
guimafelipe Oct 4, 2025
6e369aa
Style changes
guimafelipe Oct 8, 2025
b4c18b0
Separating namespaces
guimafelipe Oct 8, 2025
392382a
Fixing struct
guimafelipe Oct 8, 2025
6135089
Initializing struct properties
guimafelipe Oct 8, 2025
9e6e14d
Changing error logic
guimafelipe Oct 8, 2025
97c9ba5
NIT changes on deployer.cpp
guimafelipe Oct 8, 2025
0067c0b
Changing LRP error message
guimafelipe Oct 8, 2025
264a094
Moving license installer proxy to its own file
guimafelipe Oct 8, 2025
1a5dc32
New line at end of file
guimafelipe Oct 8, 2025
3efa5e0
New line at end of file 2
guimafelipe Oct 8, 2025
660bc3b
Adding correct includes
guimafelipe Oct 8, 2025
061bde8
Some tweaks on code
guimafelipe Oct 13, 2025
fab4936
Some tweaks on code 2
guimafelipe Oct 13, 2025
71a46a4
These are on pch
guimafelipe Oct 13, 2025
6d85985
Tyding up headers a bit
guimafelipe Oct 14, 2025
4949039
Separating deployer into two namespaces
guimafelipe Oct 21, 2025
49e5b9d
Fixing proxy include
guimafelipe Oct 21, 2025
e3e8354
Moving LRP restart out of deployment function
guimafelipe Oct 21, 2025
f3f3d58
Fixing LRP injection on test
guimafelipe Oct 21, 2025
bed2de6
Merge branch 'main' into user/felipeda/refactordeployment
guimafelipe Oct 21, 2025
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
24 changes: 24 additions & 0 deletions WindowsAppRuntime.sln
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mrmmin", "dev\MRTCore\mrt\m
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MRM", "dev\MRTCore\mrt\Core\src\MRM.vcxproj", "{CF03CC8D-FFF1-4CDC-B773-D219AD4E6F76}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeploymentUnitTests", "test\DeploymentUnitTests\DeploymentUnitTests.vcxproj", "{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DeploymentUnitTests", "DeploymentUnitTests", "{2ECD5D10-0811-44D3-A789-B2C330BA8DF6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsAppSDK.Test.NetCore", "test\WindowsAppSDK.Test.NetCore\WindowsAppSDK.Test.NetCore.csproj", "{BF580B26-B869-3AF1-43EC-D0FD55A49E4D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsAppSDK.Test.SampleTests", "test\WindowsAppSDK.Test.SampleTests\WindowsAppSDK.Test.SampleTests.csproj", "{346E099B-45E4-FF40-E63D-8B34915223C1}"
Expand Down Expand Up @@ -2592,6 +2596,22 @@ Global
{CF03CC8D-FFF1-4CDC-B773-D219AD4E6F76}.Release|x64.Build.0 = Release|x64
{CF03CC8D-FFF1-4CDC-B773-D219AD4E6F76}.Release|x86.ActiveCfg = Release|Win32
{CF03CC8D-FFF1-4CDC-B773-D219AD4E6F76}.Release|x86.Build.0 = Release|Win32
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Debug|Any CPU.ActiveCfg = Debug|x64
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Debug|Any CPU.Build.0 = Debug|x64
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Debug|ARM64.ActiveCfg = Debug|ARM64
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Debug|ARM64.Build.0 = Debug|ARM64
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Debug|x64.ActiveCfg = Debug|x64
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Debug|x64.Build.0 = Debug|x64
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Debug|x86.ActiveCfg = Debug|Win32
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Debug|x86.Build.0 = Debug|Win32
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Release|Any CPU.ActiveCfg = Release|x64
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Release|Any CPU.Build.0 = Release|x64
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Release|ARM64.ActiveCfg = Release|ARM64
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Release|ARM64.Build.0 = Release|ARM64
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Release|x64.ActiveCfg = Release|x64
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Release|x64.Build.0 = Release|x64
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Release|x86.ActiveCfg = Release|Win32
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34}.Release|x86.Build.0 = Release|Win32
{BF580B26-B869-3AF1-43EC-D0FD55A49E4D}.Debug|Any CPU.ActiveCfg = Debug|x64
{BF580B26-B869-3AF1-43EC-D0FD55A49E4D}.Debug|Any CPU.Build.0 = Debug|x64
{BF580B26-B869-3AF1-43EC-D0FD55A49E4D}.Debug|ARM64.ActiveCfg = Debug|arm64
Expand Down Expand Up @@ -2847,6 +2867,8 @@ Global
{E9C055BB-6AE4-497A-A354-D07841E68976} = {022E355A-AB24-48EE-9CC0-965BEFDF5E8C}
{DC453DE3-18FD-43E7-8103-20763C8B97C8} = {5012149E-F09F-4F18-A03C-FFE597203821}
{C40AE1D8-FD5F-472E-86B5-DDA5ABA6FF99} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D}
{F2A9B8E7-4C62-4D89-9A4F-829F8E2A7E34} = {2ECD5D10-0811-44D3-A789-B2C330BA8DF6}
{2ECD5D10-0811-44D3-A789-B2C330BA8DF6} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D}
{BF580B26-B869-3AF1-43EC-D0FD55A49E4D} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D}
{346E099B-45E4-FF40-E63D-8B34915223C1} = {8630F7AA-2969-4DC9-8700-9B468C1DC21D}
EndGlobalSection
Expand Down Expand Up @@ -2901,5 +2923,7 @@ Global
dev\VersionInfo\VersionInfo.vcxitems*{e3edec7f-a24e-4766-bb1d-6bdfba157c51}*SharedItemsImports = 9
dev\AppNotifications\AppNotificationBuilder\AppNotificationBuilder.vcxitems*{e49329f3-5196-4bba-b5c4-e11ce7efb07a}*SharedItemsImports = 9
test\inc\inc.vcxitems*{e5659a29-fe68-417b-9bc5-613073dd54df}*SharedItemsImports = 4
dev\Common\Common.vcxitems*{f2a9b8e7-4c62-4d89-9a4f-829f8e2a7e34}*SharedItemsImports = 4
test\inc\inc.vcxitems*{f2a9b8e7-4c62-4d89-9a4f-829f8e2a7e34}*SharedItemsImports = 4
EndGlobalSection
EndGlobal
164 changes: 164 additions & 0 deletions dev/Deployment/Deployer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// Copyright (c) Microsoft Corporation and Contributors.
// Licensed under the MIT License.

#include <pch.h>
#include <DeploymentActivityContext.h>
#include <PackageDefinitions.h>
#include <Deployer.h>
#include <PackageUtilities.h>
#include <PackageRegistrar.h>
#include <functional>

using namespace winrt;

namespace WindowsAppRuntime::Deployment::Deployer
{
// licenseFileSpec: This parameter specifies the file specification (e.g., path and pattern) for the license files to be retrieved.
// licenseFiles: This is an output parameter that will be populated with the names of the license files found matching the specified file specification.
HRESULT GetLicenseFiles(const std::wstring& licenseFileSpec, std::vector<std::wstring>& licenseFiles)
{
licenseFiles.clear();

WIN32_FIND_DATA findFileData{};
wil::unique_hfind hfind{ FindFirstFileW(licenseFileSpec.c_str(), &findFileData) };
if (!hfind)
{
const auto lastError{ GetLastError() };
RETURN_HR_IF_MSG(HRESULT_FROM_WIN32(lastError), (lastError != ERROR_FILE_NOT_FOUND) && (lastError != ERROR_PATH_NOT_FOUND),
"FindFirstFile:%ls", licenseFileSpec.c_str());
return S_OK;
}
for (;;)
{
// Add the license file
licenseFiles.push_back(findFileData.cFileName);

// Next! (if any)
if (!FindNextFileW(hfind.get(), &findFileData))
{
const auto lastError{ GetLastError() };
RETURN_HR_IF(HRESULT_FROM_WIN32(lastError), lastError != ERROR_NO_MORE_FILES);
break;
}
}
return S_OK;
}

HRESULT InstallLicenses(
const std::vector<std::wstring>& licenseFiles,
std::filesystem::path licensePath,
ILicenseInstaller& licenseInstaller,
::WindowsAppRuntime::Deployment::Activity::Context& initializeActivityContext
)
{
initializeActivityContext.SetInstallStage(::WindowsAppRuntime::Deployment::Activity::DeploymentStage::InstallLicense);

// Deploy the licenses (if any)
for (const auto& licenseFileName : licenseFiles)
{
// Install the license file
auto licenseFileFullName{ licensePath };
licenseFileFullName /= licenseFileName;

// initializeActivityContext.Reset(); --> Why are we reseting here? It clears out all the info.
initializeActivityContext.SetCurrentResourceId(licenseFileFullName);

RETURN_IF_FAILED_MSG(licenseInstaller.InstallLicenseFile(licenseFileFullName.c_str()),
"LicenseFile:%ls", licenseFileFullName.c_str());
}
return S_OK;
}

std::vector<DeploymentPackageArguments> GetDeploymentPackageArguments(
const std::wstring& frameworkPackageFullName,
::WindowsAppRuntime::Deployment::Activity::Context& initializeActivityContext,
const std::function<std::wstring(const std::wstring&)>& getPackagePathFunc)
{
initializeActivityContext.Reset();
initializeActivityContext.SetInstallStage(::WindowsAppRuntime::Deployment::Activity::DeploymentStage::GetPackagePath);

std::vector<DeploymentPackageArguments> deploymentPackageArguments;

const auto frameworkPath{ std::filesystem::path(getPackagePathFunc(frameworkPackageFullName)) };
for (auto package : winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implementation::c_targetPackages)
{
auto isSingleton{ CompareStringOrdinal(package.identifier.c_str(), -1, WINDOWSAPPRUNTIME_PACKAGE_SUBTYPENAME_SINGLETON, -1, TRUE) == CSTR_EQUAL };

std::filesystem::path packagePath{};

// If there is exisiting target package version higher than that of framework current version package, then re-register it.
// Otherwise, deploy the target msix package from the current framework package version.
auto existingPackageIfHigherVersion = winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implementation::g_existingTargetPackagesIfHigherVersion.find(package.identifier);
auto useExistingPackageIfHigherVersion { existingPackageIfHigherVersion != winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implementation::g_existingTargetPackagesIfHigherVersion.end() };
if (useExistingPackageIfHigherVersion)
{
packagePath = std::filesystem::path(getPackagePathFunc(existingPackageIfHigherVersion->second));
packagePath /= WINDOWSAPPRUNTIME_PACKAGE_MANIFEST_FILE;
}
else
{
packagePath = frameworkPath;
packagePath /= WINDOWSAPPRUNTIME_FRAMEWORK_PACKAGE_FOLDER;
packagePath /= package.identifier + WINDOWSAPPRUNTIME_FRAMEWORK_PACKAGE_FILE_EXTENSION;
}

deploymentPackageArguments.push_back(DeploymentPackageArguments{ package.identifier, packagePath, useExistingPackageIfHigherVersion, isSingleton });
}

return deploymentPackageArguments;
}

HRESULT DeployPackages(
const std::vector<DeploymentPackageArguments>& deploymentPackageArguments,
const bool forceDeployment,
::WindowsAppRuntime::Deployment::Activity::Context& initializeActivity,
const std::function<HRESULT()>& startupNotificationsLongRunningPlatformFunc
)
{
for (auto package : deploymentPackageArguments)
{
initializeActivity.Reset();
initializeActivity.SetInstallStage(::WindowsAppRuntime::Deployment::Activity::DeploymentStage::AddPackage);
initializeActivity.SetCurrentResourceId(package.packageIdentifier);
if (package.useExistingPackageIfHigherVersion)
{
initializeActivity.SetUseExistingPackageIfHigherVersion();
}

// If the current application has runFullTrust capability, then Deploy the target package in a Breakaway process.
// Otherwise, call PackageManager API to deploy the target package.
// The Singleton package will always set true for forceDeployment and the running process will be terminated to update the package.
if (initializeActivity.GetIsFullTrustPackage())
{

RETURN_IF_FAILED(::WindowsAppRuntime::Deployment::PackageRegistrar::AddOrRegisterPackageInBreakAwayProcess(
package.packagePath,
package.useExistingPackageIfHigherVersion,
forceDeployment || package.isSingleton,
initializeActivity,
::WindowsAppRuntime::Deployment::PackageRegistrar::GenerateDeploymentAgentPath()
));
}
else
{
auto packageManager = winrt::Windows::Management::Deployment::PackageManager{};
RETURN_IF_FAILED(::WindowsAppRuntime::Deployment::PackageRegistrar::AddOrRegisterPackage(
package.packagePath,
package.useExistingPackageIfHigherVersion,
forceDeployment || package.isSingleton,
packageManager,
initializeActivity
));
}

// Always restart Push Notifications Long Running Platform when Singleton package is processed and installed.
if (package.isSingleton)
{
// wil callback is set up to log telemetry events for Push Notifications LRP.
LOG_IF_FAILED_MSG(startupNotificationsLongRunningPlatformFunc(), "Restarting Notifications LRP failed in all 3 attempts.");
}
}

return S_OK;
}
}
50 changes: 50 additions & 0 deletions dev/Deployment/Deployer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) Microsoft Corporation and Contributors.
// Licensed under the MIT License.
#pragma once

#include <string>
#include <filesystem>
#include <vector>
#include <functional>
#include <DeploymentActivityContext.h>

namespace WindowsAppRuntime::Deployment::Deployer
{
// Structure to hold deployment package arguments
struct DeploymentPackageArguments
{
const std::wstring packageIdentifier;
const std::filesystem::path packagePath;
const bool useExistingPackageIfHigherVersion;
const bool isSingleton;
};

// Proxy/Wrapper for license installer. Open possibility to add more methods if needed.
struct ILicenseInstaller
{
virtual HRESULT InstallLicenseFile(const std::wstring& licenseFilename) = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why a pure virtual base class?

At a minimum, why not a NOOP base class? e.g.

virtual HRESULT InstallLicenseFile([[maybe_unused]] const std::wstring& licenseFilename)
{
    return S_OK;
}

Copy link
Contributor Author

@guimafelipe guimafelipe Oct 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not accounting for that to ever happen. It forces it to receive an implementation. I think it make it clear that this is an argument that needs to be passed to the function and doesn't have a default implementation.

};

// Get license files from the specified path pattern
HRESULT GetLicenseFiles(const std::wstring& licenseFileSpec, std::vector<std::wstring>& licenseFiles);

// Install license files
HRESULT InstallLicenses(
const std::vector<std::wstring>& licenseFiles,
std::filesystem::path licensePath,
ILicenseInstaller& licenseInstaller,
::WindowsAppRuntime::Deployment::Activity::Context& initializeActivityContext);

// Get deployment package arguments
std::vector<DeploymentPackageArguments> GetDeploymentPackageArguments(
const std::wstring& frameworkPackageFullName,
::WindowsAppRuntime::Deployment::Activity::Context& initializeActivityContext,
const std::function<std::wstring(const std::wstring&)>& getPackagePathFunc);

// Package deployment
HRESULT DeployPackages(
const std::vector<DeploymentPackageArguments>& deploymentPackageArguments,
const bool forceDeployment,
::WindowsAppRuntime::Deployment::Activity::Context& initializeActivity,
const std::function<HRESULT()>& startupNotificationsLongRunningPlatformFunc);
}
6 changes: 6 additions & 0 deletions dev/Deployment/Deployment.vcxitems
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,19 @@
<ClInclude Include="$(MSBuildThisFileDirectory)DeploymentResult.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)DeploymentActivityContext.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)PackageDefinitions.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Deployer.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)PackageUtilities.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)PackageRegistrar.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)DeploymentTraceLogging.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)DeploymentInitializeOptions.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)DeploymentManager.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)DeploymentResult.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)DeploymentActivityContext.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Deployer.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)PackageUtilities.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)PackageRegistrar.cpp" />
</ItemGroup>
<ItemGroup>
<PublicHeaders Include="$(MSBuildThisFileDirectory)DeploymentManagerAutoInitializer.cs" />
Expand Down
Loading
Loading