1. MSIX Package Management
January 26, 2026 ยท View on GitHub
This feature provides package management APIs comparable to those in namespace Windows.Management.Deployment but with additional functionality, improved developer experience and performance optimizations.
- 1. MSIX Package Management
- 2. Background
- 3. Description
- 4. Examples
- 4.1. AddPackageAsync()
- 4.2. AddPackageByUriAsync()
- 4.3. AddPackageSetAsync()
- 4.4. EnsurePackageSetReadyAsync()
- 4.5. IsPackageSetReady() and EnsurePackageSetReadyAsync()
- 4.6. PackageRuntimeManager.AddPackageSet()
- 4.7. PackageRuntimeManager.RemovePackageset()
- 4.8. PackageVolume.Repair()
- 4.9. IsPackageProvisioned()
- 5. Remarks
- 6. API Details
2. Background
Windows supports the ability to deploy and manage software as MSIX packages via WinRT APIs in the Windows.Management.Deployment namespace. These APIs provide the means to install, update, uninstall, enumerate and otherwise manage packages.
The package management APIs were originally introduced in Windows 8 and have continuously expanded to meet MSIX's growing demands over the past decade. However, as one of the earliest WinRT APIs they include some patterns out of step with current API practices and recommendations. Windows App SDK offers the opportunity to provide a new generation of package management APIs in line with the latest patterns and recommendations for an improved developer experience as well as functional enhancements and improved runtime efficiencies.
Microsoft-internal task 45952398
3. Description
This API provides enhanced access to Windows' package management capabilities, focusing on the following scenarios:
- Stage a package
- Register a package
- Add/Update a package
- Remove a package
- Repair a package
- Reset a package
- Provision a package
- Deprovision a package
Additional functionality includes:
- IsReady* -- Is a package ready for use?
- EnsureReady -- Is a package ready for use and, if not, make it so
- IsPackageRegistrationPending -- Is there an update waiting to register?
- PackageSets -- Batch operations
- PackageRuntimeManager -- Batch operations for use at runtime via Dynamic Dependencies
- Package validation -- Validate a package has expected identity, signature, etc. before adding/staging
- Usability -- Quality-of-Life enhancements
3.1. API Structure
Methods to drive deployment activity typically follow the pattern:
<verb>Package[Set][By<Type>][Suffix]Async(target, options)
The following verbs are supported:
- Is...Ready[OrNewerAvailable]
- Ensure...Ready
- Add
- Stage
- Register
- Remove
- Repair
- Reset
- Provision
- Deprovision
These methods accept their target package(s) as their first parameter. This parameter can be an various types of information including:
- Filename
- Path
- PackageFamilyName
- PackageFullName
- Uri
NOTE: Methods with a target of a URI are named ...ByUri....
NOTE: Methods with a target of a PackageFamilyName are named ...ByPackageFamilyName....
NOTE: Methods with a target of a PackageFullName are named ...ByPackageFullName....
NOTE: Methods with no ...By
These methods accept options as a matching <verb>Package[Set]Options type, e.g.
AddPackageAsync(string packageUri, AddPackageOptions options).
The following table shows the supported permutations of verbs and targets:
| Verb | Path | Filename | PackageFamilyName | PackageFullName | file: | http(s): | ms-uup: | PackageSet |
|---|---|---|---|---|---|---|---|---|
| IsReady | X | X | OS/WAS | WAS | X | X | WAS | WAS |
| IsReadyOrNewerAvailable | X | X | OS/WAS | WAS | X | X | WAS | WAS |
| EnsureReady | X | X | X | X | X | X | WAS | WAS |
| Add | OS/WAS | X | X | X | OS/WAS | OS/WAS | OS/WAS | WAS |
| Stage | OS/WAS | X | X | X | OS/WAS | OS/WAS | OS/WAS | WAS |
| Register | WAS | OS/WAS | OS/WAS | OS/WAS | OS/WAS | X | OS/WAS | WAS |
| Remove | X | X | WAS | OS/WAS | X | X | OS/WAS | WAS |
| Repair | X | X | WAS | WAS | X | X | WAS | WAS |
| Reset | X | X | WAS | WAS | X | X | WAS | WAS |
| IsProvisioned | X | X | OS/WAS | X | X | X | WAS | WAS |
| Provision | X | X | OS/WAS | X | X | X | WAS | WAS |
| Deprovision | X | X | OS/WAS | X | X | X | WAS | WAS |
Legend:
- OS = Supported by Windows (OS) APIs in the Windows.Management.Deployment.PackageManager namespace.
- WAS = Supported by Windows App SDK APIs in the Microsoft.Windows.Management.Deployment.PackageDeploymentManager namespace.
- X = Not supported
3.2. Is*Ready()
Is*Ready() methods determine if the target is installed (registered) and ready for use. Reasons why a package is not ready can include:
- The package is not present on the machine
- The package is present on the machine but not registered for the user
- The package is registered for the user but is not in a healthy status e.g. its Package.Status=Tampered
Is*Ready() methods are a quick test to determine if more (costly) work is needed before the target can be used.
3.3. Is*ReadyOrNewerAvailable()
Is*ReadyOrNewerAvailable() methods determine if the target is installed (registered) and ready for use AND if a newer version is locally available. Reasons why a package is ready but a newer version is available can include:
- The package is registered for the user but a newer version is available locally on the machine e.g. a user has package v1 registered and Windows Update downloaded and staged v2 in the background while app(s) are running using v1.
Is*ReadyOrNewerAvailable() methods are a quick test to determine if more (costly) work is needed before the target can be used.
NOTE: Is*ReadyOrNewerAvailable() can only determine a newer package is available than a package
installed (registered) and ready for use. If Is*Ready() returns false then
Is*ReadyOrNewerAvailable() will never return NewerAvailable.
NOTE: Is*ReadyOrNewerAvailable() does not require admin privilege. PackageManager.FindPackages() and PackageManager.FindPackagesForUser(user!=currentuser...) can enumerate packages regardless if staged or registered for the user but requires admin privilege.
3.4. Ensure*Ready()
Ensure*Ready() methods determine if the target is installed and ready for use and, if not, makes it so. This can include downloading the target, registering it for the user and remediating a package in an unhealthy state.
Thus EnsurePackageReady(pkg, options) is functionally equivalent to
var pdm = PackageDeploymentManager().GetDefault();
if (!pdm.IsPackageReady(pkg))
{
var result = await pdm.AddPackageAsync(pkg, options);
}
3.4.1. Why Is*Ready() Given Ensure*Ready()?
Ensure*Ready() performs an 'is ready' check and returns if all is ready. There's no efficiency reasons to call Is*Ready() before Ensure*Ready() (in fact, it's less efficient as Is*Ready() would occur twice).
However, this can be useful if you need additional work before potentially performing deployment operations. For example, if you need to prompt the user for consent before installing the target e.g.
var pdm = PackageDeploymentManager().GetDefault();
if (!pdm.IsPackageReady(pkg))
{
bool ok = AskUserForConsent(pkg);
if (ok)
{
var options = new EnsureReadyOptions();
var result = await pdm.EnsurePackageReadyAsync(pkg, options);
}
}
3.4.2. EnsureReadyOptions.RegisterNewerIfAvailable
Ensure*Ready() performs an 'is ready' check via Is*ReadyOrNewerAvailable() if
EnsureReadyOptions.RegisterNewerIfAvailable = true.
There's no efficiency reasons to call Is*ReadyOrNewerAvailable() before Ensure*Ready(...options.RegisterNewerIfAvailable=true) (in fact, it's less efficient as Is*ReadyOrNewerAvailable() would occur twice).
However, this can be useful if you need additional work before potentially performing deployment operations. For example, if you need to prompt the user for consent before registering ('installing') or updating the package e.g.
var pdm = PackageDeploymentManager().GetDefault();
var status = pdm.IsPackageReadyOrNewerAvailable(pkg);
if (status != PackageReadyOrNewerAvailableStatus.Ready)
{
bool ok = AskUserForConsent(pkg, status);
if (ok)
{
var options = new EnsureReadyOptions();
options.RegisterNewerIfAvailable = true;
var result = await pdm.EnsurePackageReadyAsync(pkg, options);
}
}
3.5. Repair
PackageDeploymentManager offers Repair APIs providing the same functionality as available
interactively via Settings' Repair button on the detail page for an app (via Apps > Installed
Apps > ... menu's Advanced options).
3.6. Reset
PackageDeploymentManager offers Reset APIs providing the same functionality as available
interactively via Settings' Reset button on the detail page for an app (via Apps > Installed
Apps > ... menu's Advanced options).
3.7. IsPackageRegistrationPending
IsPackageRegistrationPending() detects if package registration is pending for the specified target. For
example, if a package is in use and AddPackageByUriAsync() is called with a newer version and the
option
DeferRegistrationWhenPackagesAreInUse=true
then the registration is delayed until the package is no longer in use and can be updated. In such
cases IsPackageRegistrationPending() returns true.
3.8. PackageSet
A PackageSet is a group of packages to be operated on with one request. Package sets provide a
convenient means to perform multiple operations.
NOTE: There is no ordering guarantee of items processed in a PackageSet.
For example, IsPackageSetReady(ps) returns true only if all packages referenced by the
PackageSet are ready for use. For another example, AddPackageSetAsync(ps, options) is
functionally equivalent to
var pdm = PackageDeploymentManager().GetDefault();
foreach (PackageSetItem psi in ps.Items)
{
var result = await pdm.AddPackageAsync(psi.PackageUri, options)
if (result.Status != PackageDeploymentStatus.CompletedSuccess)
{
return result;
}
}
return new PackageDeploymentResult(PackageDeploymentStatus.CompletedSuccess);
3.8.1. PackageSet Properties
Id is optional. This is used primarily for logging and troubleshooting.
Items is required to contain 1+ item.
PackageUri is optional. This is used if a PackageUri is needed for a PackageSetItem but the
PackageSetItem.PackageUri is not specified.
3.8.2. PackageSetItem Properties
Id is required and used primarily for logging and troubleshooting.
MinVersion is optional. If not set the default value is 0.0.0.0. Some verbs use this property (see below).
PackageFamilyName is optional. Some verbs require this property (see below).
PackageUri is optional. If a PackageUri is needed and this is not set the PackageSet's PackageUri property is used. Some verbs require this property (see below).
ProcessorArchitectureFilter is optional. If not set the default value is Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependencyProcessorArchitectures.None. Only some verbs use this property (see below).
| Verb | MinVersion | PackageFamilyName | PackageUri | ProcessorArchitectureFilter |
|---|---|---|---|---|
| IsReady | Used | Required | N/A | Optional |
| IsReadyOrNewerAvailable | Used | Required | N/A | Optional |
| EnsureReady | Used | Required | Used | Optional |
| Add | N/A | N/A | Used | N/A |
| Stage | N/A | N/A | Used | N/A |
| Register | N/A | Used-if-no-PackageUri | Optional | N/A |
| Remove | N/A | Used-if-no-PackageUri | Optional | N/A |
| Repair | N/A | Used-if-no-PackageUri | Optional | N/A |
| Reset | N/A | Used-if-no-PackageUri | Optional | N/A |
| IsProvisioned | N/A | Used | Optional | N/A |
| Provision | N/A | Used-if-no-PackageUri | Optional | N/A |
| Deprovision | N/A | Used-if-no-PackageUri | Optional | N/A |
Legend:
- N/A = Not applicable. This property is not used.
- Optional = This property is used, if specified.
- Required = This property is required.
- Used = This property is used; if not specified, the default value is used.
3.9. PackageRuntimeManager
The PackageRuntimeManager API provides Dynamic Dependency support for PackageSet operations,
especially when the caller may not know the exact package(s) involved (for instance, when targeting
packages via ms-uup:). PackageRuntimeManager determines the packages involved for a PackageSet
and dynamically adds them to the caller's package graph.
3.10. PackageVolume Repair
Packages are typically1 installed to a
PackageVolume,
For example, C:\Program Files\WindowsApps is the default PackageVolume on a new Windows system.
Windows pairs a PackageVolume with the underlying storage volume's media ID to identify the
PackageVolume even when mount points change. For example, insert USB flash key and it's mount point
is E:, then remove the USB flash key and later reinsert it but now it's mounted as K:. The
PackageVolume is recognized at K: now because it volume K: has the media ID associated with the
PackageVolume.
It's possible this tracking information can be invalidated, e.g. backup a drive's content, replace the drive with a new one and then restore the content. The packages installed on this drive's PackageVolume(s) aren't recognized by Windows because the new drive has a different media ID.
The Windows App SDK's new PackageVolume.Repair() will attempt to detect these and other like
conditions and correct them.
PackageVolume.IsRepairNeeded() checks if the PackageVolume is OK or in need of repair.
NOTE: Repair() requires admin privilege (IsRepairNeeded() doesn't).
1 RegisterPackageOptions.DevelopmentMode, AddPackageOptions.StageInPlace and other options canalter the typical behavior and install packages to a non-PackageVolume location.
3.11. Usability
The package management API in Windows App SDK provides several quality-of-life enhancements over the package management APIs in Windows (e.g. Windows.Management.Deployment.PackageManager) including:
PackageManager.AddPackageByUriAsync(p)fails returningERROR_INSTALL_PACKAGE_DOWNGRADEif a newer version of the package is already installed.PackageDeploymentManagersucceeds as it treats the request as "install this package or higher version", as dependencies and other package references are routinely handled.PackageManager.AddPackageByUriAsync(p)fails returningERROR_PACKAGE_ALREADY_EXISTSif that exact version of the package is already installed.PackageDeploymentManagersucceeds as the requested package is installed.- Many
PackageManageroperations accept a target package as a file but require it expressed as aUri.PackageDeploymentManagerprovides overrides also accepting it as aString. PackageManager.RemovePackageByFullNameAsync(p)fails if the specified package isn't found.PackageDeploymentManagersucceeds as the requested package is not present at the end of the operation.- This follows the core deployment principle "'Tis not the journey that matters but the destination". In short, it doesn't matter the current state of the system, only the desired end state is achieved.
PackageManagermethods accept inconsistent (and often inconvenient) permutations of expressing a target package. For example,PackageManagersupports removing a package by PackageFullName but not PackageFamilyName.PackageDeploymentManagerprovides a richer API accepting additional identifiers.
3.12. Is*Provisioned()
Is*Provisioned*() methods determine if the target is provisioned.
These methods require administrative privileges.
3.13. Package Validation
This API allows callers to verify that packages being processed by Add*, Ensure*, and Stage* APIs of PackageDeploymentManager match what are expected from their URI.
When adding or staging a package from an external source such as HTTP URI or uncontrolled file location, a malicious actor might perform a man-in-the-middle attack to intercept and tamper with the package data being read, causing a malicious package to be installed instead of the expected one. The package might also be tampered at the source through supply-chain attacks. Verifying the identity and signature of target packages helps ensure that such attacks have not happened.
The following package validators are available for use directly through their runtimeclasses:
PackageFamilyNameValidator: Validates that the package has the expected package family name.PackageMinimumVersionValidator: Validates that the package has at least the expected minimum version number.PackageCertificateEkuValidator: Validates that the certificate used to sign the package contains the expected Extended Key Usage (EKU) value.
Package validators can be customized to verify any part of packages'
footprint data
(manifest, block map, and digital signature). Custom package validators can be implemented as
handlers for the PackageValidationEventSource.ValidationRequested event. The
PackageValidationHandler runtimeclass provides a standard implementation of such a handler,
and accepts any implementation class derived from the IPackageValidator interface.
4. Examples
4.1. AddPackageAsync()
Fabrikam app installing Contoso's Muffin package from a .msix file.
void Install()
{
var package = "d:\\contoso\\muffin.msix";
var packageDeploymentManager = PackageDeploymentManager.GetDefault();
var options = new AddPackageOptions();
var deploymentResult = await packageDeploymentManager.AddPackageAsync(package, options);
if (deplymentResult.Status == PackageDeploymentStatus.CompletedSuccess)
{
Console.WriteLine("OK");
}
else
{
Console.WriteLine("Error:{} ExtendedError:{} {}",
deploymentResult.Error.HResult, deploymentResult.ExtendedError.HResult, deploymentResult.ErrorText);
}
}
4.2. AddPackageByUriAsync()
Fabrikam app installing Contoso's Muffin package from an https: source.
void Install()
{
var package = new Uri("https://contoso.com/muffin.msix");
var packageDeploymentManager = PackageDeploymentManager.GetDefault();
var options = new AddPackageOptions();
var deploymentResult = await packageDeploymentManager.AddPackageByUriAsync(package, options);
if (deplymentResult.Status == PackageDeploymentStatus.CompletedSuccess)
{
Console.WriteLine("OK");
}
else
{
Console.WriteLine("Error:{} ExtendedError:{} {}",
deploymentResult.Error.HResult, deploymentResult.ExtendedError.HResult, deploymentResult.ErrorText);
}
}
NOTE: This differs from the AddPackageAsync() example by the method name
(AddPackageByUriAsync() instead of AddPackageAsync()) and the target type (https: source as URI
instead of filename as string).
4.3. AddPackageSetAsync()
Fabrikam app installing Contoso's Muffin and Waffle packages via a PackageSet.
void Install()
{
var packageSet = new PackageSet() {
Items = { new PackageSetItem() { PackageUri = new Uri("c:\\contoso\\muffin-1.2.3.4.msix") },
{ new PackageSetItem() { PackageUri = new Uri("https://contoso.com/waffle-2.4.6.8.msix") } };
var packageDeploymentManager = PackageDeploymentManager.GetDefault();
var options = new AddPackageOptions();
var deploymentResult = await packageDeploymentManager.AddPackageByUriAsync(packageSet, options);
if (deplymentResult.Status == PackageDeploymentStatus.CompletedSuccess)
{
Console.WriteLine("OK");
}
else
{
Console.WriteLine("Error:{} ExtendedError:{} {}",
deploymentResult.Error.HResult, deploymentResult.ExtendedError.HResult, deploymentResult.ErrorText);
}
}
NOTE: This differs from the AddPackageByUriAsync() example by the method name
(AddPackageSetAsync instead of AddPackageByUriAsync()), the target type (PackageSet containing
2 URIs instead of a URI), and installing 2 packages instead of 1.
4.4. EnsurePackageSetReadyAsync()
Fabrikam app installing Contoso's Muffin and Waffle packages if necessary via a PackageSet.
void Install()
{
var packageSet = new PackageSet() {
Items = { new PackageSetItem() { PackageFamilyName = "contoso.muffin_1234567890abc",
MinVersion = ToVersion(1, 2, 3, 4),
PackageUri = new Uri("c:\\contoso\\muffin-1.2.3.4.msix") },
{ new PackageSetItem() { PackageFamilyName = "contoso.waffle_1234567890abc",
MinVersion = ToVersion(2, 4, 6, 8),
PackageUri = new Uri("https://contoso.com/waffle-2.4.6.8.msix") } };
var packageDeploymentManager = PackageDeploymentManager.GetDefault();
var options = new EnsureReadyOptions();
var deploymentResult = await packageDeploymentManager.EnsurePackageSetReadyAsync(packageSet, options);
if (deplymentResult.Status == PackageDeploymentStatus.CompletedSuccess)
{
Console.WriteLine("OK");
}
else
{
Console.WriteLine("Error:{} ExtendedError:{} {}",
deploymentResult.Error.HResult, deploymentResult.ExtendedError.HResult, deploymentResult.ErrorText);
}
}
PackageVersion ToVersion(uint major, uint minor, uint build, uint revision) =>
new PackageVersion {
Major = checked((ushort)major),
Minor = checked((ushort)minor),
Build = checked((ushort)build),
Revision = checked((ushort)revision)
};
NOTE: This differs from the AddPackageBySetAsync() example by the method name
(EnsurePackageSetReadyAsync() instead of AddPackageSetAsync), the addition of
PackageFamilyName and MinVersion for each item in the PackageSet and the packages will only be
installed if necessary.
4.5. IsPackageSetReady() and EnsurePackageSetReadyAsync()
Fabrikam app installing Contoso's Muffin and Waffle packages if necessary, and with explicit user confirmation before the installation.
void Install()
{
var packageSet = new PackageSet() {
Items = { new PackageSetItem() { PackageFamilyName = "contoso.muffin_1234567890abc",
MinVersion = ToVersion(1, 2, 3, 4),
PackageUri = new Uri("c:\\contoso\\muffin-1.2.3.4.msix") },
{ new PackageSetItem() { PackageFamilyName = "contoso.waffle_1234567890abc",
MinVersion = ToVersion(2, 4, 6, 8),
PackageUri = new Uri("https://contoso.com/waffle-2.4.6.8.msix") } };
var packageDeploymentManager = PackageDeploymentManager.GetDefault();
if (!packageDeploymentManager.IsPackageSetReady(packageSet))
{
bool ok = PromptUserForConfirmation();
if (!ok)
{
return;
}
}
var options = new EnsureReadyOptions();
var deploymentResult = await packageDeploymentManager.EnsurePackageSetReadyAsync(packageSet, options);
if (deplymentResult.Status == PackageDeploymentStatus.CompletedSuccess)
{
Console.WriteLine("OK");
}
else
{
Console.WriteLine("Error:{} ExtendedError:{} {}",
deploymentResult.Error.HResult, deploymentResult.ExtendedError.HResult, deploymentResult.ErrorText);
}
}
PackageVersion ToVersion(uint major, uint minor, uint build, uint revision) =>
new PackageVersion {
Major = checked((ushort)major),
Minor = checked((ushort)minor),
Build = checked((ushort)build),
Revision = checked((ushort)revision)
};
NOTE: This differs from the EnsurePackageSetReadyAsync() example checking if
EnsurePackageSetReadyAsync() will need to do any work and prompting the user to confirm it's OK
to proceed.
4.6. PackageRuntimeManager.AddPackageSet()
Fabrikam app uses Contoso's Muffin and Waffle packages via Dynamic Dependencies, installing them if necessary. These packages are added to the package graph and not explicitly removed (they stay in the package graph until process termination).
void AddMuffinsAndWafflesToThePackageGraph()
{
var packageSet = new PackageSet() {
Items = { new PackageSetItem() { PackageFamilyName = "contoso.muffin_1234567890abc",
MinVersion = ToVersion(1, 2, 3, 4),
PackageUri = new Uri("c:\\contoso\\muffin-1.2.3.4.msix") },
{ new PackageSetItem() { PackageFamilyName = "contoso.waffle_1234567890abc",
MinVersion = ToVersion(2, 4, 6, 8),
PackageUri = new Uri("https://contoso.com/waffle-2.4.6.8.msix") } };
var packageDeploymentManager = PackageDeploymentManager.GetDefault();
var options = new EnsureReadyOptions();
var deploymentResult = await packageDeploymentManager.EnsurePackageSetReadyAsync(packageSet, options);
if (deplymentResult.Status == PackageDeploymentStatus.CompletedSuccess)
{
Console.WriteLine("OK");
}
else
{
Console.WriteLine("Error:{} ExtendedError:{} {}",
deploymentResult.Error.HResult, deploymentResult.ExtendedError.HResult, deploymentResult.ErrorText);
}
var packageRuntimeManager = PackageRuntimeManager.GetDefault();
var packageSetRuntimeDisposition = packageRuntimeManager.AddPackageSet(packageSet);
}
PackageVersion ToVersion(uint major, uint minor, uint build, uint revision) =>
new PackageVersion {
Major = checked((ushort)major),
Minor = checked((ushort)minor),
Build = checked((ushort)build),
Revision = checked((ushort)revision)
};
NOTE: This differs from the EnsurePackageSetReadyAsync() example adding the packages
referenced by the PackageSet to the process' package graph for subsequent access of the content.
4.7. PackageRuntimeManager.RemovePackageset()
Fabrikam app uses Contoso's Muffin and Waffle packages via Dynamic Dependencies, installing them if necessary. These packages are added to the package graph and later removed when no longer needed.
void DoAwesomeStuffUsingMuffinsAndWaffles()
{
var packageSet = new PackageSet() {
Items = { new PackageSetItem() { PackageFamilyName = "contoso.muffin_1234567890abc",
MinVersion = ToVersion(1, 2, 3, 4),
PackageUri = new Uri("c:\\contoso\\muffin-1.2.3.4.msix") },
{ new PackageSetItem() { PackageFamilyName = "contoso.waffle_1234567890abc",
MinVersion = ToVersion(2, 4, 6, 8),
PackageUri = new Uri("https://contoso.com/waffle-2.4.6.8.msix") } };
var packageDeploymentManager = PackageDeploymentManager.GetDefault();
var options = new EnsureReadyOptions();
var deploymentResult = await packageDeploymentManager.EnsurePackageSetReadyAsync(packageSet, options);
if (deplymentResult.Status == PackageDeploymentStatus.CompletedSuccess)
{
Console.WriteLine("OK");
}
else
{
Console.WriteLine("Error:{} ExtendedError:{} {}",
deploymentResult.Error.HResult, deploymentResult.ExtendedError.HResult, deploymentResult.ErrorText);
}
var packageRuntimeManager = PackageRuntimeManager.GetDefault();
var packageSetRuntimeDisposition = packageRuntimeManager.AddPackageSet(packageSet);
DoAwesomeStuff();
packageRuntimeManager.RemovePackageSet(packageSetRuntimeDisposition);
}
PackageVersion ToVersion(uint major, uint minor, uint build, uint revision) =>
new PackageVersion {
Major = checked((ushort)major),
Minor = checked((ushort)minor),
Build = checked((ushort)build),
Revision = checked((ushort)revision)
};
NOTE: This differs from the PackageRuntimeManager.AddPackageSet()() example by explicitly removing the packages dynamically added to the package graph when no longer needed.
4.8. PackageVolume.Repair()
Fabrikam app checks if a PackageVolume is OK and if not, prompts the user to confirm it should proceed to repair the PackageVolume.
void CheckAndFixPackageVolume(string packageStorePath)
{
var packageVolume = PackageVolume.FindPackageVolumeByPath(packageStorePath);
if (packageVolume.IsRepairNeeded())
{
bool ok = PromptUserForConfirmation();
if (!ok)
{
return;
}
}
packageVolume.Repair();
}
4.9. IsPackageProvisioned()
Fabrikam app installing Contoso's Muffin and Waffle packages for all users if necessary, and with explicit user confirmation before the installation.
void Install()
{
// We want to check what's provisioned by PackageFamilyName. If something's
// not provisioned we'll also need MinVersion and PackageUri to Stage and
// Provision. But checking if a family is provisioned only supports some
// URI schemes (notably, not the one we need for our staging work). So we'll
// define the PackageSet with the families we want checked and if something's
// not provisioned we'll add the additional properties needed.
var packageSet = new PackageSet() {
Items = { new PackageSetItem() { PackageFamilyName = "contoso.muffin_1234567890abc" },
{ new PackageSetItem() { PackageFamilyName = "contoso.waffle_1234567890abc" }
}
};
var packageDeploymentManager = PackageDeploymentManager.GetDefault();
if (packageDeploymentManager.IsPackageSetProvisioned(packageSet))
{
return;
}
bool ok = PromptUserForConfirmation();
if (!ok)
{
return;
}
packageSet.Items()[0].MinVersion(ToVersion(1, 2, 3, 4));
packageSet.Items()[0].PackageUri(new Uri("c:\\contoso\\muffin-1.2.3.4.msix"));
packageSet.Items()[1].MinVersion(ToVersion(2, 4, 6, 8));
packageSet.Items()[1].PackageUri(new Uri("https://contoso.com/waffle-2.4.6.8.msix"));
var stageOptions = new StagePackageOptions();
var deploymentResult = await packageDeploymentManager.StagePackageSetReadyAsync(packageSet, options);
if (deplymentResult.Status == PackageDeploymentStatus.CompletedSuccess)
{
Console.WriteLine("Staged");
}
else
{
Console.WriteLine("Error:{} ExtendedError:{} {}",
deploymentResult.Error.HResult, deploymentResult.ExtendedError.HResult, deploymentResult.ErrorText);
return;
}
var options = new ProvisionPackageOptions();
var deploymentResult = await packageDeploymentManager.ProvisionPackageSetReadyAsync(packageSet, options);
if (deplymentResult.Status == PackageDeploymentStatus.CompletedSuccess)
{
Console.WriteLine("Provisioned");
}
else
{
Console.WriteLine("Error:{} ExtendedError:{} {}",
deploymentResult.Error.HResult, deploymentResult.ExtendedError.HResult, deploymentResult.ErrorText);
}
}
PackageVersion ToVersion(uint major, uint minor, uint build, uint revision) =>
new PackageVersion {
Major = checked((ushort)major),
Minor = checked((ushort)minor),
Build = checked((ushort)build),
Revision = checked((ushort)revision)
};
4.9. Package Validation
4.9.1. Using built-in package validators
This example shows how to use built-in package validators to verify package family name, minimum version, and certificate EKU.
using Microsoft.Windows.Management.Deployment;
var pdm = PackageDeploymentManager().GetDefault();
var packageUri = new Uri("https://contoso.com/package.msix");
var options = new AddPackageOptions();
var validators = options.GetValidationEventSourceForUri(packageUri).ValidationRequested;
validators += new PackageValidationHandler(new PackageFamilyNameValidator("ExpectedFamilyName_1234567890abc")).Handler;
validators += new PackageValidationHandler(new PackageMinimumVersionValidator(new Windows.ApplicationModel.PackageVersion(2, 0, 0, 0))).Handler;
validators += new PackageValidationHandler(new PackageCertificateEkuValidator("1.3.6.1.4.1.311.2.1.11")).Handler;
var deploymentResult = await pdm.AddPackageAsync(packageUri, options);
if (deploymentResult.Status == PackageDeploymentStatus.CompletedSuccess)
{
Console.WriteLine("Success");
}
else // deploymentResult.Status == PackageDeploymentStatus.CompletedFailure
{
var error = deploymentResult.Error.HResult;
if (error = 0x80080219 /*APPX_E_DIGEST_MISMATCH*/)
{
Console.WriteLine("The package retrieved from the specified URI doesn't have the expected family name, version, or certificate EKU");
}
else
{
var extendedError = deploymentResult.ExtendedError.HResult;
var message = deploymentResult.MessageText;
Console.WriteLine($"An error occurred while adding the package. Error 0x{error:X08} ExtendedError 0x{extendedError:X08} {message}");
}
}
4.9.2. Using IPackageValidator to implement custom package validator
This example shows how to implement and use a custom package validator derived from the
IPackageValidator interface to validate a .msix package.
using Microsoft.Windows.Management.Deployment;
// Consuming COM APIs for IAppxPackageReader, IAppxManifestReader, etc. requires C# interop definitions.
// Assume standard interop definitions exist for relevant APIs in AppxPackaging.h.
[Guid("b5c49650-99bc-481c-9a34-3d53a4106708"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAppxPackageReader { ... }
// Implementation of the custom package validator
// This example validates that the package has no capabilities declared in its manifest.
class PackageCapabilitiesValidator : IPackageValidator
{
public bool IsPackageValid(object package)
{
var packageReader = package as IAppxPackageReader;
if (packageReader == null)
{
// object is not a .msix package as expected (i.e. it is a bundle), reject it
return false;
}
var manifestReader = packageReader.GetManifest() as IAppxManifestReader3;
var capabilitiesEnumerator = manifestReader.GetCapabilitiesByCapabilityClass(APPX_CAPABILITY_CLASS_ALL);
bool hasCapabilities = capabilitiesEnumerator.GetHasCurrent();
return !hasCapabilities;
}
}
// Code that utilizes the custom package validator
void InstallPackageWithCustomValidation()
{
var pdm = PackageDeploymentManager().GetDefault();
var packageUri = new Uri("https://contoso.com/package.msix");
var options = new AddPackageOptions();
options.GetValidationEventSourceForUri(packageUri).ValidationRequested += new PackageValidationHandler(new PackageCapabilitiesValidator()).Handler;
var deploymentResult = await pdm.AddPackageAsync(packageUri, options);
if (deploymentResult.Status == PackageDeploymentStatus.CompletedSuccess)
{
Console.WriteLine("Success");
}
else // deploymentResult.Status == PackageDeploymentStatus.CompletedFailure
{
var error = deploymentResult.Error.HResult;
if (error = 0x80080219 /*APPX_E_DIGEST_MISMATCH*/)
{
Console.WriteLine("The package retrieved from the specified URI did not pass validation for capabilities");
}
else
{
var extendedError = deploymentResult.ExtendedError.HResult;
var message = deploymentResult.MessageText;
Console.WriteLine($"An error occurred while adding the package. Error 0x{error:X08} ExtendedError 0x{extendedError:X08} {message}");
}
}
}
4.9.3. Using custom package validator as event handler
This example shows how to implement and use a custom package validator as an event handler
for the PackageValidationEventSource.ValidationRequested event to validate a .msix package.
using Microsoft.Windows.Management.Deployment;
// Consuming COM APIs for IAppxPackageReader, IAppxManifestReader, etc. requires C# interop definitions.
// Assume standard interop definitions exist for relevant APIs in AppxPackaging.h.
[Guid("b5c49650-99bc-481c-9a34-3d53a4106708"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAppxPackageReader { ... }
// Implementation of the custom package validator
// This example validates that the package has no capabilities declared in its manifest.
void MyPackageValidationHandler(object sender, PackageValidationEventArgs args)
{
var deferral = args.GetDeferral();
bool isValid = false;
try
{
var packageReader = args.Package as IAppxPackageReader;
if (packageReader == null)
{
// object is not a .msix package as expected (i.e. it is a bundle), reject it
return false;
}
var manifestReader = packageReader.GetManifest() as IAppxManifestReader3;
var capabilitiesEnumerator = manifestReader.GetCapabilitiesByCapabilityClass(APPX_CAPABILITY_CLASS_ALL);
bool hasCapabilities = capabilitiesEnumerator.GetHasCurrent();
isValid = !hasCapabilities;
}
finally
{
if (isValid)
{
Log("Package at URI is valid: " + args.PackageUri);
}
else
{
Log("Package at URI is not valid: " + args.PackageUri);
args.Cancel = true;
}
deferral.Complete();
}
}
// Code that utilizes the custom package validator
void InstallPackageWithCustomValidation()
{
var pdm = PackageDeploymentManager().GetDefault();
var packageUri = new Uri("https://contoso.com/package.msix");
var options = new AddPackageOptions();
options.GetValidationEventSourceForUri(packageUri).ValidationRequested += MyPackageValidationHandler;
var deploymentResult = await pdm.AddPackageAsync(packageUri, options);
if (deploymentResult.Status == PackageDeploymentStatus.CompletedSuccess)
{
Console.WriteLine("Success");
}
else // deploymentResult.Status == PackageDeploymentStatus.CompletedFailure
{
var error = deploymentResult.Error.HResult;
if (error = 0x80080219 /*APPX_E_DIGEST_MISMATCH*/)
{
Console.WriteLine("The package retrieved from the specified URI did not pass validation for capabilities");
}
else
{
var extendedError = deploymentResult.ExtendedError.HResult;
var message = deploymentResult.MessageText;
Console.WriteLine($"An error occurred while adding the package. Error 0x{error:X08} ExtendedError 0x{extendedError:X08} {message}");
}
}
}
5. Remarks
5.1. Platform Support
This API is only available on Windows >= 10.0.19041.0 (aka 2004 aka 20H1).
A subset of functionality is available on newer releases, e.g. AddPackageOptions.ExpectedDigests
requires Windows >= 10.0.22621.0 (aka Win11 22H2). Any
functionality requiring newer releases of windows than then 20H1 baseline has affordances to detect at runtime if the current platform supports the feature e.g.
var options = new AddPackageOptions();
if (options.IsLimitToExistingPackagesSupported)
{
options.LimitToExistingPackages = true;
}
6. API Details
namespace Microsoft.Windows.Management.Deployment
{
[contractversion(3)]
apicontract PackageDeploymentContract{};
/// Represents a package storage volume.
/// @note A volume 'name' is the volume's media ID (you can treat 'Volume Name' == 'Volume Media ID').
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume
/// @see https://learn.microsoft.com/windows/win32/properties/props-system-volumeid
/// @see https://learn.microsoft.com/sysinternals/downloads/volumeid
/// @see https://learn.microsoft.com/windows/win32/api/fileapi/nf-fileapi-getvolumenameforvolumemountpointw
[contract(PackageDeploymentContract, 1)]
runtimeclass PackageVolume
{
/// Gets all the known volumes, regardless of their current state.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.findpackagevolumes
static IVector<PackageVolume> FindPackageVolumes();
/// Get the specified volume.
/// @param packageStorePath a path on the volume e.g. "F:", "F:\Foo\Bar", "\\?\Volume{dd992d3d-8505-4adb-a622-82cdc2398a29}\"
/// and "\\?\Volume{dd992d3d-8505-4adb-a622-82cdc2398a29}\Foo\Bar" are equally valid.
/// @note The packageStorePath parameter is used to identify the device Volume.
/// The actual path for packages in a PackageVolume is defined by Windows.
/// @return the volume or null if not found.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.findpackagevolume
/// @see GetPackageVolumeByPath()
///
/// @note This API is deprecated and will be removed in a future release.
/// Use GetPackageVolumeByPath().
static PackageVolume FindPackageVolumeByPath(String packageStorePath);
/// Get the specified volume.
/// @param path a path on the volume e.g. "F:", "F:\Foo\Bar", "\\?\Volume{dd992d3d-8505-4adb-a622-82cdc2398a29}\"
/// and "\\?\Volume{dd992d3d-8505-4adb-a622-82cdc2398a29}\Foo\Bar" are equally valid.
/// @note The path parameter is used to identify the device Volume.
/// The actual path for packages in a PackageVolume is defined by Windows.
/// @return the volume or null if not found.
/// @see GetPackageVolumeByName()
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.findpackagevolume
[contract(PackageDeploymentContract, 3)]
static PackageVolume GetPackageVolumeByPath(String path);
/// Get the specified volume.
/// @name The volume media ID (a GUID value)
/// @see GetPackageVolumeByName()
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.findpackagevolume
///
/// @note This API is deprecated and will be removed in a future release.
/// Use GetPackageVolumeByName().
static PackageVolume FindPackageVolumeByName(String name);
/// Get the specified volume.
/// @name The volume media ID (a GUID value)
/// @see GetPackageVolumeByPath()
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.findpackagevolume
[contract(PackageDeploymentContract, 3)]
static PackageVolume GetPackageVolumeByName(String name);
/// Return true if the package volume is an internal system volume mapped to the %SYSTEMDRIVER% environment variable.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.issystemvolume
Boolean IsSystemVolume{ get; };
/// Get the path of the last known mount point for the package volume.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.mountpoint
String MountPoint{ get; };
/// Get the media ID of the package volume.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.name
String Name{ get; };
/// Get the absolute path for the Package store on the volume.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.packagestorepath
String PackageStorePath{ get; };
/// Return true if the package volume supports the creation of hard links in its file system.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.supportshardlinks
Boolean SupportsHardLinks{ get; };
/// Return true if APPX installing is supported.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.isappxinstallsupported
Boolean IsAppxInstallSupported{ get; };
/// Return true if full-trust packages are supported.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.isfulltrustpackagesupported
Boolean IsFullTrustPackageSupported{ get; };
/// Return true if the package volume is in an offline state.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagevolume.isoffline
[contract(PackageDeploymentContract, 3)]
Boolean IsOffline();
/// Return true if the package volume is damaged and needs to be repaired.
Boolean IsRepairNeeded();
/// Repair the package volume (if necessary).
void Repair();
[contract(PackageDeploymentContract, 3)]
static Boolean IsFeatureSupported(PackageVolumeFeature feature);
/// Return the default package volume.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.getdefaultpackagevolume
[contract(PackageDeploymentContract, 3)]
static PackageVolume GetDefault();
/// Set the default package volume.
/// @see //learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.setdefaultpackagevolume
[contract(PackageDeploymentContract, 3)]
void SetDefault();
/// Create a new package volume.
/// @param packageStorePath The absolute path of the Package store.
/// @note This requires admin privilege.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.addpackagevolumeasync
[contract(PackageDeploymentContract, 3)]
static Windows.Foundation.IAsyncOperation<PackageVolume> AddAsync(String packageStorePath);
/// @note The caller must be running with Medium IL (or higher)
/// OR running in an AppContainer with the packageManagement restricted capability
/// OR caller has package identity and the publisher matches the publisher of the volume being removed.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.removepackagevolumeasync
[contract(PackageDeploymentContract, 3)]
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress> RemoveAsync();
/// Set the package volume to an offline state.
/// @note This requires admin privilege.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.setpackagevolumeofflineasync
[contract(PackageDeploymentContract, 3)]
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress> SetOfflineAsync();
/// Set the package volume to an online state.
/// @note This requires admin privilege.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.packagemanager.setpackagevolumeonlineasync
[contract(PackageDeploymentContract, 3)]
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress> SetOnlineAsync();
/// Get the available space (bytes).
/// @see https://learn.microsoft.com/en-us/uwp/api/windows.management.deployment.packagevolume.getavailablespaceasync?view=winrt-26100
[contract(PackageDeploymentContract, 3)]
Windows.Foundation.IAsyncOperation<UInt64> GetAvailableSpaceAsync();
};
/// Defines the stub behavior for an app package that is being added or staged.
/// @see https://learn.microsoft.com/uwp/api/windows.management.deployment.stubpackageoption
[contract(PackageDeploymentContract, 1)]
enum StubPackageOption
{
Default,
InstallFull,
InstallStub,
UsePreference,
};
/// Defines the stub behavior for an app package that is being added or staged.
[contract(PackageDeploymentContract, 2)]
enum PackageReadyOrNewerAvailableStatus
{
NotReady = 0,
Ready = 1,
NewerAvailable = 2,
};
[contract(PackageDeploymentContract, 3)]
runtimeclass PackageValidationEventArgs
{
Windows.Foundation.Uri PackageUri{ get; };
IInspectable AppxPackagingObject{ get; };
Boolean Cancel;
Windows.Foundation.Deferral GetDeferral();
}
[contract(PackageDeploymentContract, 3)]
runtimeclass PackageValidationEventSource
{
event Windows.Foundation.TypedEventHandler<PackageValidationEventSource, PackageValidationEventArgs> ValidationRequested;
}
[contract(PackageDeploymentContract, 3)]
interface IPackageValidator
{
// This IInspectable will support QueryInterface into either IAppxPackageReader or
// IAppxBundleReader (these are COM interfaces from AppxPackaging.h).
// One of these interfaces will be available depending on the type of file being validated.
Boolean IsPackageValid(IInspectable appxPackagingObject);
}
[contract(PackageDeploymentContract, 3)]
runtimeclass PackageValidationHandler
{
PackageValidationHandler(IPackageValidator validator);
Windows.Foundation.TypedEventHandler<PackageValidationEventSource, PackageValidationEventArgs> Handler{ get; };
}
[contract(PackageDeploymentContract, 3)]
runtimeclass PackageFamilyNameValidator : [default] IPackageValidator
{
PackageFamilyNameValidator(String expectedPackageFamilyName);
}
[contract(PackageDeploymentContract, 3)]
runtimeclass PackageMinimumVersionValidator : [default] IPackageValidator
{
PackageMinimumVersionValidator(Windows.ApplicationModel.PackageVersion minimumVersion);
}
[contract(PackageDeploymentContract, 3)]
runtimeclass PackageCertificateEkuValidator : [default] IPackageValidator
{
PackageCertificateEkuValidator(String expectedCertificateEku);
}
[contract(PackageDeploymentContract, 1)]
runtimeclass PackageSetItem
{
PackageSetItem();
String Id;
String PackageFamilyName;
Windows.ApplicationModel.PackageVersion MinVersion;
Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependencyProcessorArchitectures ProcessorArchitectureFilter;
Windows.Foundation.Uri PackageUri;
}
[contract(PackageDeploymentContract, 1)]
runtimeclass PackageSet
{
PackageSet();
String Id;
Windows.Foundation.Uri PackageUri;
IVector<PackageSetItem> Items { get; };
}
// Requires Windows >= 10.0.19041.0 (aka 2004 aka 20H1)
[contract(PackageDeploymentContract, 1)]
runtimeclass AddPackageOptions
{
AddPackageOptions();
PackageVolume TargetVolume;
IVector<Windows.Foundation.Uri> DependencyPackageUris { get; };
IVector<String> OptionalPackageFamilyNames { get; };
IVector<Windows.Foundation.Uri> OptionalPackageUris { get; };
IVector<Windows.Foundation.Uri> RelatedPackageUris { get; };
Windows.Foundation.Uri ExternalLocationUri;
StubPackageOption StubPackageOption;
Boolean AllowUnsigned;
Boolean DeveloperMode;
Boolean ForceAppShutdown;
Boolean ForceTargetAppShutdown;
Boolean ForceUpdateFromAnyVersion;
Boolean InstallAllResources;
Boolean RequiredContentGroupOnly;
Boolean RetainFilesOnFailure;
Boolean StageInPlace;
Boolean DeferRegistrationWhenPackagesAreInUse;
Boolean IsExpectedDigestsSupported { get; }; // Requires Windows >= 10.0.22621.0 (aka Win11 22H2)
IMap<Windows.Foundation.Uri, String> ExpectedDigests{ get; };
Boolean IsLimitToExistingPackagesSupported { get; }; // Requires Windows >= 10.0.22621.0 (aka Win11 22H2)
Boolean LimitToExistingPackages;
[contract(PackageDeploymentContract, 3)]
Boolean IsPackageValidationSupported{ get; };
[contract(PackageDeploymentContract, 3)]
IMapView<Windows.Foundation.Uri, PackageValidationEventSource> PackageValidators{ get; };
[contract(PackageDeploymentContract, 3)]
PackageValidationEventSource GetValidationEventSourceForUri(Windows.Foundation.Uri uri);
}
// Requires Windows >= 10.0.19041.0 (aka 2004 aka 20H1)
[contract(PackageDeploymentContract, 1)]
runtimeclass StagePackageOptions
{
StagePackageOptions();
PackageVolume TargetVolume;
IVector<Windows.Foundation.Uri> DependencyPackageUris { get; };
IVector<String> OptionalPackageFamilyNames { get; };
IVector<Windows.Foundation.Uri> OptionalPackageUris { get; };
IVector<Windows.Foundation.Uri> RelatedPackageUris { get; };
Windows.Foundation.Uri ExternalLocationUri;
StubPackageOption StubPackageOption;
Boolean DeveloperMode;
Boolean ForceUpdateFromAnyVersion;
Boolean InstallAllResources;
Boolean RequiredContentGroupOnly;
Boolean StageInPlace;
Boolean AllowUnsigned;
Boolean IsExpectedDigestsSupported { get; }; // Requires Windows >= 10.0.22621.0 (aka Win11 22H2)
IMap<Windows.Foundation.Uri, String> ExpectedDigests{ get; };
[contract(PackageDeploymentContract, 3)]
Boolean IsPackageValidationSupported{ get; };
[contract(PackageDeploymentContract, 3)]
IMapView<Windows.Foundation.Uri, PackageValidationEventSource> PackageValidators{ get; };
[contract(PackageDeploymentContract, 3)]
PackageValidationEventSource GetValidationEventSourceForUri(Windows.Foundation.Uri uri);
}
// Requires Windows >= 10.0.19041.0 (aka 2004 aka 20H1)
[contract(PackageDeploymentContract, 1)]
runtimeclass RegisterPackageOptions
{
RegisterPackageOptions();
PackageVolume AppDataVolume;
IVector<String> DependencyPackageFamilyNames { get; };
IVector<Windows.Foundation.Uri> DependencyPackageUris { get; };
IVector<String> OptionalPackageFamilyNames { get; };
Windows.Foundation.Uri ExternalLocationUri;
Boolean AllowUnsigned;
Boolean DeveloperMode;
Boolean ForceAppShutdown;
Boolean ForceTargetAppShutdown;
Boolean ForceUpdateFromAnyVersion;
Boolean InstallAllResources;
Boolean StageInPlace;
Boolean DeferRegistrationWhenPackagesAreInUse;
Boolean IsExpectedDigestsSupported { get; }; // Requires Windows >= 10.0.22621.0 (aka Win11 22H2)
IMap<Windows.Foundation.Uri, String> ExpectedDigests{ get; };
}
// Requires Windows >= 10.0.19041.0 (aka 2004 aka 20H1)
[contract(PackageDeploymentContract, 1)]
runtimeclass RemovePackageOptions
{
RemovePackageOptions();
Boolean FailIfNotFound;
Boolean PreserveApplicationData;
Boolean PreserveRoamableApplicationData;
Boolean RemoveForAllUsers;
}
[contract(PackageDeploymentContract, 1)]
runtimeclass ProvisionPackageOptions
{
ProvisionPackageOptions();
Boolean IsOptionalPackageFamilyNamesSupported{ get; }; // Requires Windows >= 10.0.22000.0 (aka Win11 21H2)
IVector<String> OptionalPackageFamilyNames { get; };
Boolean IsProjectionOrderPackageFamilyNamesSupported{ get; }; // Requires Windows >= 10.0.22000.0 (aka Win11 21H2)
IVector<String> ProjectionOrderPackageFamilyNames { get; };
}
[contract(PackageDeploymentContract, 1)]
runtimeclass EnsureReadyOptions
{
EnsureReadyOptions();
AddPackageOptions AddPackageOptions { get; };
[contract(PackageDeploymentContract, 2)]
Boolean RegisterNewerIfAvailable;
}
[contract(PackageDeploymentContract, 1)]
runtimeclass PackageDeploymentManager
{
// Get an instance of the manager
static PackageDeploymentManager GetDefault();
//-------------------------------------------------------------
// IsPackageDeploymentFeatureSupported
[contract(PackageDeploymentContract, 2)]
static Boolean IsPackageDeploymentFeatureSupported(PackageDeploymentFeature feature);
//-------------------------------------------------------------
// IsReady
// Return true if the package(s) are present and available for use
Boolean IsPackageReady(String package);
// Return true if the package(s) are present and available for use
Boolean IsPackageReadyByUri(Windows.Foundation.Uri packageUri);
// Return true if the package(s) are present and available for use
/// @note packageSet[Item].PackageUri is optional
Boolean IsPackageSetReady(PackageSet packageSet);
//-------------------------------------------------------------
// IsReadyOrNewerAvailable
// Return true if the package(s) are present and available for use
[contract(PackageDeploymentContract, 2)]
PackageReadyOrNewerAvailableStatus IsPackageReadyOrNewerAvailable(String package);
// Return true if the package(s) are present and available for use
[contract(PackageDeploymentContract, 2)]
PackageReadyOrNewerAvailableStatus IsPackageReadyOrNewerAvailableByUri(Windows.Foundation.Uri packageUri);
// Return true if the package(s) are present and available for use
/// @note packageSet[Item].PackageUri is optional
[contract(PackageDeploymentContract, 2)]
PackageReadyOrNewerAvailableStatus IsPackageSetReadyOrNewerAvailable(PackageSet packageSet);
//-------------------------------------------------------------
// EnsureReady
// Check if the necessary package(s) are present
// and available for use and if not then Make It So.
// If the necessary packages(s) are not present on the system
// then make them available (download, install, etc).
// If the necessary packages are present and available this is equivalent to IsReady(id).
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
EnsurePackageReadyAsync(String package, EnsureReadyOptions options);
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
EnsurePackageReadyByUriAsync(Windows.Foundation.Uri packageUri, EnsureReadyOptions options);
/// @note packageSet[Item].PackageUri is required
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
EnsurePackageSetReadyAsync(PackageSet packageSet, EnsureReadyOptions options);
//-------------------------------------------------------------
// Add packages
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
AddPackageAsync(String package, AddPackageOptions options);
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
AddPackageByUriAsync(Windows.Foundation.Uri packageUri, AddPackageOptions options);
/// @note packageSet[Item].PackageUri is required
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
AddPackageSetAsync(PackageSet packageSet, AddPackageOptions options);
//-------------------------------------------------------------
// Stage packages
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
StagePackageAsync(String package, StagePackageOptions options);
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
StagePackageByUriAsync(Windows.Foundation.Uri packageUri, StagePackageOptions options);
/// @note packageSet[Item].PackageUri is required
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
StagePackageSetAsync(PackageSet packageSet, StagePackageOptions options);
//-------------------------------------------------------------
// Register packages
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
RegisterPackageAsync(String package, RegisterPackageOptions options);
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
RegisterPackageByUriAsync(Windows.Foundation.Uri packageUri, RegisterPackageOptions options);
/// @note packageSet[Item].PackageUri is optional
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
RegisterPackageSetAsync(PackageSet packageSet, RegisterPackageOptions options);
//-------------------------------------------------------------
// Remove packages
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
RemovePackageAsync(String package, RemovePackageOptions options);
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
RemovePackageByFullNameAsync(String packageFullName, RemovePackageOptions options);
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
RemovePackageByFamilyNameAsync(String packageFamilyName, RemovePackageOptions options);
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
RemovePackageByUriAsync(Windows.Foundation.Uri packageUri, RemovePackageOptions options);
/// @note packageSet[Item].PackageUri is optional
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
RemovePackageSetAsync(PackageSet packageSet, RemovePackageOptions options);
//-------------------------------------------------------------
// Reset packages
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
ResetPackageAsync(String package);
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
ResetPackageByUriAsync(Windows.Foundation.Uri packageUri);
/// @note packageSet[Item].PackageUri is optional
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
ResetPackageSetAsync(PackageSet packageSet);
//-------------------------------------------------------------
// Repair packages
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
RepairPackageAsync(String package);
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
RepairPackageByUriAsync(Windows.Foundation.Uri packageUri);
/// @note packageSet[Item].PackageUri is optional
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
RepairPackageSetAsync(PackageSet packageSet);
//-------------------------------------------------------------
// IsProvisioned
// Return true if the package(s) are provisioned
[contract(PackageDeploymentContract, 2)]
Boolean IsPackageProvisioned(String package);
// Return true if the package(s) are provisioned
[contract(PackageDeploymentContract, 2)]
Boolean IsPackageProvisionedByUri(Windows.Foundation.Uri packageUri);
// Return true if the package(s) are provisioned
/// @note packageSet[Item].PackageUri is optional
[contract(PackageDeploymentContract, 2)]
Boolean IsPackageSetProvisioned(PackageSet packageSet);
//-------------------------------------------------------------
// Provision packages
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
ProvisionPackageAsync(String package, ProvisionPackageOptions options);
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
ProvisionPackageByUriAsync(Windows.Foundation.Uri packageUri, ProvisionPackageOptions options);
/// @note packageSet[Item].PackageUri is optional
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
ProvisionPackageSetAsync(PackageSet packageSet, ProvisionPackageOptions options);
//-------------------------------------------------------------
// Deprovision packages
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
DeprovisionPackageAsync(String package);
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
DeprovisionPackageByUriAsync(Windows.Foundation.Uri packageUri);
/// @note packageSet[Item].PackageUri is optional
Windows.Foundation.IAsyncOperationWithProgress<PackageDeploymentResult, PackageDeploymentProgress>
DeprovisionPackageSetAsync(PackageSet packageSet);
//-------------------------------------------------------------
// IsRegistrationPending
/// @warning The parameter should be "packageFullName" but can't due to http://task.ms/53280356.
/// Consider the current (wrong) parameter name deprecated until vFuture (2.0) when we can change to the new (right) parameter name.
Boolean IsPackageRegistrationPending(String packageFamilyName);
/// @warning The parameter should be "packageFullName" but can't due to http://task.ms/53280356.
/// Consider the current (wrong) parameter name deprecated until vFuture (2.0) when we can change to the new (right) parameter name.
Boolean IsPackageRegistrationPendingForUser(String userSecurityId, String packageFamilyName);
}
[contract(PackageDeploymentContract, 1)]
runtimeclass PackageSetItemRuntimeDisposition
{
PackageSetItemRuntimeDisposition();
String PackageSetItemId{ get; };
String PackageFullName{ get; };
String PackageDependencyId{ get; };
Microsoft.Windows.ApplicationModel.DynamicDependency.PackageDependencyContextId PackageDependencyContextId{ get; };
}
[contract(PackageDeploymentContract, 1)]
runtimeclass PackageSetRuntimeDisposition
{
PackageSetRuntimeDisposition();
String PackageSetId;
IVector<PackageSetItemRuntimeDisposition> PackageSetItemRuntimeDispositions { get; };
}
[contract(PackageDeploymentContract, 1)]
runtimeclass PackageRuntimeManager
{
// Get an instance of the manager
static PackageRuntimeManager GetDefault();
// Make the package(s) in the package set available to the calling process
// i.e. dynamically add the package(s) in the package set to the caller's package graph.
// This is equivalent to
// FOREACH psi IN packageSet.Items
// pd = TryCreatePackageDependency(psi)
// AddPackageDependency(pd)
Microsoft.Windows.Management.Deployment.PackageSetRuntimeDisposition AddPackageSet(
PackageSet packageSet);
[method_name("AddPackageSetWithOptions")]
Microsoft.Windows.Management.Deployment.PackageSetRuntimeDisposition AddPackageSet(
PackageSet packageSet,
Microsoft.Windows.ApplicationModel.DynamicDependency.CreatePackageDependencyOptions createOptions,
Microsoft.Windows.ApplicationModel.DynamicDependency.AddPackageDependencyOptions addOptions);
void RemovePackageSet(
Microsoft.Windows.Management.Deployment.PackageSetRuntimeDisposition packageSetRuntimeDisposition);
}
}