advanced MSI packaging

YOU’RE READING

MSIX Packaging Fundamentals

by Tim Mangan, Bogdan Mitrache & Kevin Kaminski

Download ebook

Fundamental Packaging Concepts

So far, we’ve covered the core concepts that we recommend you understand before you start building your first MSIX packages.

Going forward, we’ll explore the options you have when application compatibility issues arise, how you can customize your enterprise deployments and what scripting options MSIX gives you.

Scripting

A traditional installer unpacks file and registry items and spreads them around the system as required. Under MSIX, these items are unpackaged into an isolated area, and the package Manifest describes any integrations that are required to be present outside of this isolated area (such as shortcuts and file associations).

Traditional installers also tend to perform customizable actions, investigating the environment and making changes based on what it finds. Even if the application vendor’s installer doesn’t do this, quite often the larger organizations that distribute applications to many users tend to either repackage these customizations, or add scripts to do so.

These customizations may be used to perform licensing operations, configure appropriate back-end servers (especially for dev/test/prod), or determine if integrations with additional applications are required.

Out of the box, MSIX does not support installation time customizations, but when you use PSF, you enable scripting. PSF Scripting is configured and controlled via the Json configuration file and implemented by PsfLauncher.

Scripts may only be triggered by two events: the start and the end of a process. Although there is no “install” script trigger, the “RunOnce” feature of the start trigger provides the effect of an installation script. The RunOnce feature writes a small marker in the Application Registry Hive so that subsequent launches will not run the script again.

The scripts for your packages must be written in PowerShell as PS1 files, and if you need to use the “wait” and “stop on error” features., the script must return a “0” to indicate success.

In a script triggered by the start event, the "wait" feature makes the launcher wait for the script to run to completion before starting the target application. When "wait" is requested, there is a timeout value that must be provided (in milliseconds) and is used as the maximum wait time. If this time is exceeded, it is considered an error, and the application will only be launched at that time if “stop on error” was not specified.

NoteYou may want to reference file locations in your script that are dependent on the package installation location (which is dependent on the package name and AppX Volume mounting) or where the redirected user profiles are (dependent on the package name and user name).

To help you with this, PsfLauncher supports two pseudo-variables that you can use in the Json file as script arguments. These are:

Pseudo-variable

Meaning

%MsixPackageRoot%

The root folder of the installed package.

%MsixWritablePackageRoot%

The user’s LocalAppData is for file redirection for this package.

The PsfLauncher will decode these arguments which can be passed into your script. However, your script should not contain these syntaxes as "environment variables" because they are not; the PsfLauncher must do that decoding and pass the equivalent path as the argument to your script.

PsfLauncher scripting requires an additional file to be placed in the package. This file named “StartingScriptWrapper.ps1”, is part of the PSF and should be placed in the folder alongside the copy of the PsfLauncher. This Ps1 file is used for both the start and the end trigger scripts and its name can not be changed. Also, the Json configuration will only reference the additional Ps1 file that you provide.

PsfLauncher will call StartingScriptWrapper.ps1 with your script filename and arguments from the Json added as command line arguments.StartingScriptWrapper will manage the run of the script for you.

NoteTo allow these PowerShell scripts to be executed, you may need to adjust the execution policy. You can do this through a Group Policy Object and set it to Unrestricted or RemoteSigned.
There is also an option to request ByPass mode on the script, however, you should not use this if the GPO is in place.
System changes to the execution policy must be performed on both x64 and x86 PowerShell executables.

Some packaging tools, like Advanced Installer, provide you with a predefined support to visually add and configure the scripts in your package, as part of their integration with the Package Support Framework.

Adding PowerShell scripts inside an MSIX, with Advanced Installer

MSIX Modification Packages

MSIX Modification Package is a type of MSIX package format introduced by Microsoft with the goal of decoupling customizations from the main application. Launched with the release of their MSIX packaging format, the MSIX Modification Package is an MSIX package meant to store the customizations of the application.Is the MSIX Modification Package the new MST equivalent?

If you are familiar with Windows Installer technology, then you know that, just as with the MSIX Modification Packages, Transform files (MSTs) are meant to store the customizations of an MSI package. But that is as far as the similarities go for them.

MST files can be applied to the base MSI only at the time of installation and through the same msiexec command.

For a broader perspective, let’s compare MSIX Modification Packages with Windows Installer Patches (MSPs). Although an MSP is applied to the MSI in the same way that an MSIX Modification Package is applied to the MSIX - there are two differences:

  • It cannot be installed on its own
  • It can be applied at any time (at installation time or later).

MSPs are meant to store other resources (bug fixes, security updates, and hotfixes), but not customizations.

In summary, the MSIX Modification Package is similar to MST because they both are meant to store customizations and, because they both are packaged separately from the target package.

Ultimately, the Modification Package can only deliver new or updated file and registry values. It cannot add additional applications, shortcuts, or any extension such as a file association or shell extension. It also has no custom runtime executed upon installation (such as a custom action in MSI).

A deep dive inside the manifest

This manifest section is always located in the AppxManifest.xml file of a modification package.

<Properties>
   <rescap6:ModificationPackage>true                                 </rescap6:ModificationPackage>
</Properties>

Also in the AppXManifest of a Modification Package, there will be a Uap4:MainPackageDependency entry which is included within the Dependencies section of the MSIX Modification Package manifest file, but not in the manifest file of the target application. It is called “TargetAppSample” in our example below.

<Dependencies>  <TargetDeviceFamily Name="Windows.Desktop"                                                MinVersion="10.0.17701.0"                                        MaxVersionTested="12.0.0.0"/>
  <uap4:MainPackageDependency Name="TargetAppSample"                                            Publisher="CN=Contoso Software,                                                   O=Contoso Corporation, C=US" /></Dependencies>

This comes with two attributes:

  • Name – it must match the identity Name of the target MSIX application.
  • Publisher – it does not have to match the identity Publisher of the target MSIX application and this information could be missing if the publisher is the same.

Also, since the MSIX Modification Package does not contain a full application, it does not have an entry point. In turn, there is no Application node within the manifest file of the MSIX Modification Package.

How does an MSIX Modification Package work?

One of the nice perks of decoupling the customization from the main application is that you will have two separate packages with no explicit relationship between them. And, since it is a separate package, you will not have to recreate the MSIX Modification Package with the same customizations each time there is a new update of the main application – obviously, as long as the customizations stored in the MSIX Modification Package are still applicable.

Not only do you not need to recreate the MSIX Modification Package, but there is no need to remove and reinstall it when a new update of the main application comes in. The customization stored in the MSIX Modification Package will apply successfully to the new MSIX package for the main application once the updated target MSIX package gets installed.

However, there's a small catch. The MSIX Modification Package doesn't contain a full application, thus it can't be installed on its own. The MSIX for the main application is required to be installed on the device prior to the MSIX Modification Package installation. If you mix-up the steps, you will be presented with an error like the one shown below:

An MSIX Modification Package cannot be installed before the target application

When an MSIX Modification Package is installed, its content will overlay (at runtime) on top of the resources from the target MSIX in a way that it will look like one application for the operating system and the main app.

ImportantThe Modification Package overlay does not work for files outside the VFS folder. Any changes outside the VFS are ignored.

Let's do a small exercise. Imagine we have an executable file that reads the content of a .config file placed next to it and displays the outcome on the screen. Our example application is being packaged into MSIX.

Now, we want to replace the .config file with a new one (customized for our enterprise environment) using an MSIX Modification Package.

NoteFor step-by-step instructions on how to create an MSIX Modification Package, you can watch our video tutorial on creating an MSIX Modification Package using the free Advanced Installer Express edition.

Now, take the MSIX Modification Package created with the new .config file included within and install that on a device where the target MSIX package is installed. App Installer will prompt a message to let you know that it will modify the target application.

App Installer message when installing an MSIX Modification Package

Once the MSIX Modification Package is installed, if we launch our application, the executable will now read the content of the new .config file included within the MSIX Modification Package.

If you go to “App Settings” for the MSIX Package, you should find the MSIX Modification Package listed under the “App add-ons & downloadable content” section, here is an example for a target package called “MyApp” and its modification package “MyModificationPackage”:

List of MSIX Modification Packages installed on the device for a specific application(“MyApp”)

Or you can achieve the same output by using Get-AppXPackage PowerShell cmdlet:

PS C:\Windows\system32> get-appxpackage -name "My Company. MyApp"
Name            	: My Company.MyApp
Publisher        	: CN=Horatiu Vladasel
Architecture    	: X64
Resourceid        	:
Version        	: 1.0.0.0
PackageFullName    	: My Company.    
                    	MyApp_1.0.0.@_x64_r21nowlrc5s2y
InstallLocation    	: C:\Program Files\WindowsApps
      	\My Company. MyApp_1.0.0.0_x64_r21nⓇw1rc5s2y
IsFramework    	: False
PackageFamilyName 	: My Company. MyApp_r21n@wirc5s2y
Publisherid     	: r21now1rc5s2y
IsResourcePackage	: False
IsBundle        	: False
IsDevelopment Mode 	: False
NonRemovable     	: False
Dependencies     	: 	 
                    	{MyCompany.MyModificationPackage
                    	_1.0.0.0_neutral _r21n@wirc5s2y}
IsPartiallyStaged 	: False
Signaturekind     	: Enterprise
Status        	: OK

Additionally, you can get a list of all installed MSIX Modification Packages using the following PowerShell cmdlet:

Get-AppPackage -PackageTypeFilter Optional

The main MSIX and the MSIX Modification Package are installed in separate folders under “C:\Program Files\WindowsApp”. When the application is launched, it will consider (“see”) both packages within a single container.

How an MSIX Modification Package is loaded by the main application

NotePlease note that C:\Program Files\WindowsApp folder is read-only and system protected.

For debugging, you can launch an external EXE (eg.: regedit.exe or cmd.exe) inside an MSIX container using Invoke-CommandInDesktopPackage PowerShell cmdlet.

Alternatively, you can use Hover - a free tool, built by the Advanced Installer team, which allows you to launch natively installed applications inside an MSIX container with just a double-click.

Basically all you have to do is to launch a cmd.exe process either using the above PS cmdlet or Hover and then navigate to the folder of the target MSIX package and execute a dir command to see the contents of the virtual folder, just as your application would “see it”, i.e. with the contents of the modification package merged inside.

Microsoft did a great job here, but there is still room for improvement. The MSIX Modification Package is an excellent opportunity for enterprises to handle the customizations of each of their MSIX packages separately.

What makes it valuable is that these customizations are now decoupled from the main application. This will save a lot of time, effort, and budget for IT professionals when packaging and deploying applications.

MSIX Framework Packages

While a Modification Package acts as a package specific overlay to a given package, the Framework Package is designed to work as a common overlay that could be used by multiple packages.

A Framework Package may consist of only files to overlay onto the files of a package that lists the Framework Package as a dependency. It also adds no applications, shortcuts, or extensions. Unlike Modification packages, Framework packages can overlay outside of the VFS area.

Existing Framework Packages come from Microsoft, and in these the files are just dll files placed at the root of the package. As this is a location always checked when an app loads a dll, the dlls in the framework package can be found without use of the PSF or LoaderSearchOrder entries being needed in the main package. We suspect any filetype may be included in a Framework Package, but we lack any specific examples or even use cases yet.

Examples of known Framework Packages from Microsoft include:

  • Microsoft.Windows.AppRuntime.1.*
  • Microsoft.DotNet.DesktopRuntime.*
  • Microsoft.VCLibs.*.UWPDesktop

A framework package is identified by a special Framework element in the AppXManifest file, such as in the following example:

<Properties>
<Framework>true</Framework>
<DisplayName>Microsoft .Net Native Runtime Package 2.2</DisplayName>
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
<Description>Microsoft .Net Native Runtime Package 2.2</Description>
<Logo>logo.png</Logo>
</Properties>

In addition to containing files, a Framework package can also introduce additional dependency packages, such as dependent Framework Packages.

Unlike the use of Modification Package, where the Modification Package had the entry to link to the main package, with the Framework Package this linkage works the other way.

The Manifest of the Framework Package has no knowledge of the individual packages that will use it, but the main package must reference the Framework Package as a dependency in its AppXManifest file. Here is an example of this:

<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19041.0" MaxVersionTested="10.0.22621.1"/>
<PackageDependency Name="Microsoft.VCLibs.140.00.UWPDesktop" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" MinVersion="14.0.32530.0"/>
</Dependencies>

Framework Packages do have some issues however. These include:

  • Framework Packages must get installed. The PackageDependency element has an available field to mark the dependency as required. In some scenarios, but not all, this will cause the dependent framework package to be installed if not present. AppAttach currently lacks this support, but also systems where Winget repositories have not been authorized will have issues.
  • The PackageDependency element does not allow for the specification of an architecture (x86 or x64). So either the creator of the Framework Package must make two packages and embed the architecture in the name, or two packages with the same name but one for each architecture. The former case allows the main package to specify which is needed. The latter appears (currently) to default to adding the architecture that matches the OS platform (typically x64) and not that of the architecture of the application inside the package.

At this time, Microsoft appears to be in a phase of figuring out that they have these issues and we don’t know what they will do about them.

The Windows.AppRuntime packages embed the architecture in the name so those work quite well today. The DotNet.Desktop.Runtimes and VCLibs do not.

NoteFor scenarios not supported currently, it might be possible to extract the files from the Framework Package and include directly in your package, or create your own Framework Package with the architecture embedded in the package name,, but we can’t recommend these actions.

Shared Package Containers

MSIX packages enable classic Win32 apps to run inside modern containers. By default, each application has its own container and cannot see or interact with any other container. So, files and registries were not shared between different MSIX packaged applications.With Shared Package Containers you can enable multiple applications to see a common set of VFS files and registry hives.A shared container configuration is defined and deployed separately from the main packages. You can deploy it even before the member packages are deployed, as the system will ignore it until the member packages become available.

The containers are defined as standard XML files. A member package of a shared container is defined using the Package Family Name, thus any additional modification packages or application updates that get deployed automatically become part of the shared container.

The most important thing to note is the package priority. The priority is established from top to bottom in the XML file, meaning that the top package will have the highest priority in case of resource conflicts.

In the following example,, it is important that the first MSIX package (Caphyon.WithoutImg) is the first in the list, otherwise, the VFS or Virtual File System merge will not happen when we launch our executable, and the image loaded by the sample application will not be seen or loaded.

For our container, the XML file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<AppSharedPackageContainer Name="ContosoContainer">
<PackageFamily Name="Caphyon.WithoutImg_r21n0w1rc5s2y"/>
<PackageFamily Name="Caphyon.TheImage_r21n0w1rc5s2y"/>
</AppSharedPackageContainer>

We left the container name as “ContosoContainer” as mentioned in the Microsoft Documentation, but feel free to change the name as you prefer.

Once the XML file is created, we can use the following PowerShell cmdlets to deploy, reset, update, and remove a Shared Package Container from the device:

Add-AppSharedPackageContainer <path>
Remove-AppSharedPackageContainer -Name <name>
Get-AppSharedPackageContainer -Name <name>
Reset-AppSharedPackageContainer -Name <name>

Win32Dependencies

There are times when a main package needs a dependency but it must be natively installed. Microsoft extended the dependency feature for this, but to date there exists only one such defined package, which is for WebView2. If Microsoft adds more approved Win32Dependencies in the future, we would expect them to add them to the table on the official documentation for this element at win32dependencies:ExternalDependency (Windows 10, Windows 11) - Windows UWP applications | Microsoft Learn

Here is an example of how this is referenced in the AppXManifest:

<Dependencies >
    	<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19041.0" MaxVersionTested="10.0.22621.1" />
    	<PackageDependency Name="Microsoft.WindowsAppRuntime.1.4" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" MinVersion="4000.1010.1349.0" />
    	<PackageDependency Name="Microsoft.DotNet.DesktopRuntime.8" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" MinVersion="8.0.0.0" />
    	<win32dependencies:ExternalDependency Name="Microsoft.WebView2" Publisher="CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" MinVersion="1.0.0.0" Optional="false" />
	</Dependencies>
	<Capabilities >
    	<rescap:Capability Name="runFullTrust" />
    	<rescap:Capability Name="internetClient" />
	</Capabilities>

Of course it is necessary to add win32dependencies to the namespace at the top of the AppXManifest file.

Also note that, specifically for WebView2, the restricted capability InternetClient must be specified. This is not needed for Win32/.Net Framework packages that use the older APIs to access web traffic, only for those using WebView2. But if you are packaging applications for your own internal use, adding in a capability declaration causes no harm when not needed.

Application Updates

MSIX deployment utilizes the concept of matching the Package Name, as referenced in the internal AppxMainifest.xml file, along with version numbers to enable good application upgrade and downgrade scenarios.

An upgrade package may be created using one of two methods:

Type

Description

Edit existing package

The original package can be opened for edit, modified, and saved using a higher Version Number. Currently, tooling vendors are supporting this scenario by using a strict editor, which prevents recapture of an traditional upgrade/patch installer. Edit scenarios involving recapture (similar to how it is done in the App-V Sequencer) is not precluded by the MSIX technology and may become available in the future as well.

New package

A completely new package can be created using the same Package Name as the original package and a higher Version Number.

When creating an upgrade package, some packaging tools use some form of file naming that involves the Package Name. Some include the Version Number in the package name by default and some do not. Care should be taken to properly identify the package filename so that each version is unique.

The MSIX installation methods in the OS will recognise a situation where a different version of the same Package Name is being installed. It is capable of performing both upgrade and downgrade operations.

By default, an upgrade or downgrade will cause the user preferences data to be retained. After installation of this version, the previously installed version will be removed for this user, and if no other user profile on the system has the previous version published it will be removed from the system completely.

Thanks to single-instance download and storage, there are significant performance benefits for a version installation. As these benefits are based on file block hashes, they should be roughly the same no matter which method for packaging the new version is used.

advanced MSI packaging

YOU’RE READING

MSIX Packaging Fundamentals

by Tim Mangan, Bogdan Mitrache & Kevin Kaminski

Download ebook