When you build Windows desktop applications, there's another stage of the project that is equally important to the development phase: the deployment. If you build the best application in the world, but the deployment process is complicated and prone to errors, your customers will be equally dissatisfied, and they will just give up.
However, the deployment technology is only one side of the coin: once you have found the right one, you need a platform to distribute it.
In this chapter, we're going to address all these challenges by going through the following topics:
We have mentioned MSIX and the Windows App SDK package model multiple times in this book. It's time to dive a little bit deeper into the topic and gain a better understanding of what MSIX can do for us.
MSIX is a new packaging technology introduced by Microsoft with the goal to solve many of the challenges that the previous installation technologies (such as MSI or ClickOnce) have created over the years. Some of these challenges include the following:
The key difference between MSIX and other technologies is that it's completely integrated into Windows. This means that many of the challenges that we have outlined are solved without requiring any extra work from the developer. Let's briefly look at all of the main advantages of this technology.
Thanks to the Windows integration, MSIX can provide two features that are especially helpful in enterprise environments, where applications are deployed across thousands of devices scattered across different locations in the world.
The first one is differential updates. Whenever you release an update of your application, as a developer, you just need to create a new MSIX package with all of the content. The package can either be used for the first installation or to update an existing installation. In the second scenario, Windows won't download the entire content of the package, but only the files that have changed from the previous version. This feature introduces advantages for both users and developers:
The second optimization is around disk space. If you install an MSIX package that contains a file, with the same hash of another file included in another MSIX package, Windows won't download it again and won't store a second copy. However, it will create a hard link so that the same file can be used by both applications. If one of the applications gets uninstalled, Windows will move the file so that it doesn't get lost.
MSIX is the successor of AppX, the original packaging format introduced in Windows 8 for Store applications. The technology has evolved over the years, and while in the beginning it was only supported by Microsoft Store, today, MSIX can be deployed with a wide range of consumer and enterprise technologies, including the following:
Also, MSIX has recently become the leading technology for deploying applications in cloud environments. Thanks to a feature called MSIX App Attach, today, you can use the same MSIX package to deploy an application either in a local environment or on Azure Virtual Desktop, that is, the Microsoft platform to create remote desktop environments, which makes it possible to access your workstation from anywhere. You can learn more about this feature at https://docs.microsoft.com/en-us/azure/virtual-desktop/what-is-app-attach.
Additionally, MSIX enables automatic updates not only in managed environments such as Microsoft Store but also in unmanaged ones like a website. We'll learn about this in more detail in the Publishing your application to Microsoft Store section.
MSIX packaged applications are installed inside a special folder, C:Program FilesWindowsApps, which is a system-protected folder. Only Windows can modify or delete the content of this folder. Additionally, when an application is installed or updated, Windows Stores the hash of each file that is included inside the package. When the application starts, Windows double-checks that the hash of these files hasn't changed. If that happens, it means that a malicious actor has changed the content of the package; therefore, Windows will block the execution. The user must repair the application before using it again, which can be done in different ways based on the way it was deployed:
Additionally, certificates play a critical role to ensure the reliability of an MSIX package. A package must be signed with a certificate trusted by the machine; otherwise, Windows will block the installation. Unlike other technologies (such as MSI), there is no way to install a package that isn't signed or that is signed with an untrusted certificate. We'll learn more about certificates in the Publishing your application to Microsoft Store section.
The Windows registry is one of the areas that is heavily affected by bad installation experiences. It's very common for applications to create new hives and keys in the registry, which are left in the system even when the application is uninstalled. This leads the registry to become fragmented, which tends to slow down Windows over time. To overcome this limitation, MSIX introduces the concept of registry virtualization, which is implemented in the following way:
This feature helps to deliver a clean uninstallation experience. When the application is uninstalled, Windows will simply delete the virtual copy of the registry, avoiding leaving any orphan registry keys on the system.
However, this feature also introduces one of the potential limitations that you must consider when you plan to adopt MSIX. Since the virtualized registry is only visible to your application, this means that you can't create keys to share information with another application, since they won't be able to see them.
One of the best practices for Windows development is to use the special AppData folder to Store data that is tightly coupled with the application. Configuration files, databases, and log files are just a few examples of data that only makes sense for your application, and, as such, they should be removed when the application is uninstalled. The AppData folder is the right place to Store these files since it lives inside the user-space; therefore, no matter whether the user is an administrator or has regular permissions, you can be safe in the knowledge that your application will always have the permission it requires to work with these files.
However, having the AppData folder in a different location from the installation leads to the same problems that we have seen with the registry. It's very common for an application to create some files in the AppData folder, just to leave them even after it has been uninstalled.
When an application is packaged with MSIX instead, all the reading and writing operations against the AppData folder are automatically redirected to the local storage of the application, which we learned about in Chapter 8, Integrating Your Application with the Windows Ecosystem. The goal is the same as the registry virtualization: when the application is uninstalled, the local storage is automatically deleted, making sure that any unnecessary files aren't left behind, wasting space on the disk.
Inside an MSIX package, you can create a special folder, called VFS (which stands for Virtual File System), that you can use to virtualize most of the system folders, such as C:Windows, C:Program Files, and more. When your application runs and it looks for files in one of these folders (for example, it's very common when you have a dependency on a runtime or a framework), first, Windows will search for them inside the VFS folder. If it doesn't find them, it will fall back to the actual system folders. Thanks to the VFS, you can solve two familiar challenges around application deployment:
On the following page, https://docs.microsoft.com/en-us/windows/msix/desktop/desktop-to-uwp-behind-the-scenes, you can find a table with all of the system folders supported by VFS and the name you must use to map them inside the VFS folder.
Now that we have learned all the main features of MSIX, let's see the things we have to bear in mind before choosing to adopt MSIX.
At the time of writing, MSIX doesn't provide all the capabilities that are supported by traditional MSI installers. Some of them will likely never be supported since they are incompatible with the goal of MSIX of providing reliable and safe installation technologies. Let's see the most important limitations to bear in mind and examine how we can overcome some of them:
You can learn more about this option at https://docs.microsoft.com/en-us/windows/msix/psf/run-scripts-with-package-support-framework.
Now you have all the tools that you need to understand whether MSIX is the right technology for your application. It's time to learn more about how an MSIX package is structured.
Compared to other deployment technologies, MSIX is a quite simple format. In fact, an MSIX package is just a compressed file, which you can open with any popular compression utility such as 7-zip or WinRAR. Inside an MSIX package, you will find the following:
The metadata inside the manifest file is used to determine two key information instances to identify an MSIX package:
The identity of an application can be customized by using the Visual Studio manifest editor, which is automatically opened when you double-click on the Package.appxmanifest file. You will find all the options under the Packaging section, as you can see in the following screenshot:
The fields that are used to calculate the PFN are Package name and Publisher. When you change them, you will observe that the Package Family Name field at the bottom will also change. Additionally, notice how the Publisher field can't be freely edited, but there's a Choose Certificate… button on the right-hand side. As we're going to learn when we talk about signing, this is one of the MSIX requirements to satisfy: the Publisher field in the manifest must always match the subject of the certificate that you're going to use to sign the package.
Now that we have learned all the features of an MSIX package, it's time to see how to create one.
There are three approaches that you can use to create an MSIX package:
If you have followed the book so far, your WinUI, WPF, or Windows Forms application should already be set up for MSIX packaging. We explored the various options in Chapter 1, Getting Started with the Windows App SDK and WinUI:
Regardless of your choice, if you right-click on the project in Visual Studio, you will find an option called Package and Publish (if you're using the single-project MSIX template) or just Publish (if you're using the Windows Application Packaging Project). Inside this menu, you will find the Create App Package option, which will start a wizard that we can use to generate an MSIX package. Let's see the various steps in more detail.
The first choice in the wizard is how you want to distribute your application:
We'll learn more about Store publishing later in this chapter.
Then, you can move on to choose the signing method.
Thanks to this step, we can choose the certificate we want to use to sign our package. As mentioned earlier, this step will be skipped if we have chosen Microsoft Store as a distribution method. We'll be able to pick a certificate from multiple sources such as the following:
You can observe these options in the following screenshot:
We'll talk about the signing options, in more detail, later.
The next step will help us to define the content of the package.
This section is very important as it defines the content of the package. This is what the section looks like:
From the preceding screenshot, we observe that we can first configure the following settings:
The second section is needed to define what packages you want to create, based on the CPU architecture. The Windows App SDK supports x86, x64, and ARM64. For each of them, you can choose the configuration mode (either Debug or Release).
You have reached the end of the wizard: now you can hit Create, and Visual Studio will build your application and create the MSIX package. Once the operation has finished, a prompt will give you a link to directly access the folder where the package has been created:
If you double-click on the MSIX package, Windows will open the user interface (provided by the AppInstaller application, which we're going to see in more detail later) that you can use to install the application on the machine:
However, the application can be installed only if the package is signed with a trusted certificate. Let's learn more.
As already mentioned, signing is a key operation when you work with MSIX packages. If the package is not signed, users won't be able to install it.
This is the experience that users will get when they try to install a package that isn't signed or has been signed with a certificate that is not trusted by the current machine:
There are three ways to obtain a code signing certificate:
Microsoft is also working on a new service, called Azure Code Signing Service, which will make the signing experience easier and cheaper. One of the downsides of public certificates is that they can be quite expensive, and they must be renewed periodically. The service isn't publicly available yet, but if you want to learn more, you can watch the following video from the MSIX team at https://www.youtube.com/watch?v=Wi-4WdpKm5E.
The key requirement to satisfy when you use a code signing certificate to sign a MSIX package is that the subject of the certificate must match the publisher entry in the manifest. Visual Studio will automatically set the correct value when you import a certificate. For example, if you explore any application published by Microsoft, you will find that the publisher in the manifest is set with the following value:
CN=Microsoft Corporation, O=Microsoft Corporation,
L=Redmond, S=Washington, C=US
A vital part of the signing process is the timestamp. Certificates have an expiration date, which can lead to a package to stop working after it's been passed. By specifying a timestamp server, you'll be able to continue installing and using the package even after the certificate has expired. You can find a list of available time stamp servers at https://gist.github.com/Manouchehri/fd754e402d98430243455713efada710.
If you're a developer working with Visual Studio, the easiest way to sign an MSIX package is to choose your certificate in the manifest editor or in the wizard we have previously seen to create an MSIX package, which supports all the options we have seen so far, including setting a timestamp server. The manifest editor will also give you the option to generate a self-signing certificate on the fly, if you don't have one, by clicking on the Create… button:
After you have chosen the certificate, Visual Studio will automatically sign the package as part of the build process when you create an MSIX package for distribution using the Create App Packages wizard.
Other options to sign an MSIX package include the following:
Signing the package with Visual Studio is a good solution when you're in the development and testing phases. However, it isn't suitable for more professional scenarios in which you want to automate the building and deployment of your application. This is because it forces you to share the certificate as part of the project, which might lead to identity theft.
In the next chapter, we'll explore other ways to sign your package. Now, it's time to talk about the distribution options.
Microsoft Store is the most efficient and straightforward way with which to distribute your application to a broader audience. It's a catalog of applications and games that is preinstalled on every Windows computer, which greatly simplifies the experience of downloading and installing applications on your machine. Users no longer have to open a browser, search for an application with a search engine, find the right website (avoiding, in the meantime, potentially malicious ones), download the installer, and execute it. With Microsoft Store, they can simply search for the app they need and, by clicking on a button, trigger the installation. The following screenshot shows Microsoft Store in the browser:
As a developer, Microsoft Store greatly simplifies the distribution experience thanks to the following features:
The starting point to publish your Windows applications to Microsoft Store is by creating a developer account at https://developer.microsoft.com/en-us/microsoft-store/register/.
There are two types of accounts, as follows:
Regardless of the type you choose, a developer account must be linked to a personal Microsoft account. You can't open it using a work account, such as the one provided by Microsoft 365. However, once the developer account has been created, you can link it to an Azure Active Directory tenant (such as the one that belongs to your company). This is so that you can enable coworkers to access the developer portal. Additionally, you can assign them distinct roles: for example, a developer can only submit apps, whereas a finance contributor can see all the financial reports. You can learn more about this configuration at https://docs.microsoft.com/en-us/windows/uwp/publish/manage-account-users.
Once your account has been set up, you can log in to the Partner Center portal at https://partner.microsoft.com/dashboard and reserve a new name, which must be unique. The name will also be used to generate the PFN, which defines the application's identity. Once the name has been reserved, you can create a new submission, where you can provide all the information that will be made visible to users: pricing, distribution markets, description, age rating, screenshots, and more. You can find a detailed description of the submission flow at https://docs.microsoft.com/en-us/windows/uwp/publish/.
However, there's one step that is significantly different based on the deployment technology you choose. In fact, Microsoft Store supports submitting both packaged applications and unpackaged applications. This is a new feature that has been introduced by the new Microsoft Store version launched in Windows 11, which is now also available on Windows 10.
Let's see the specific details about how to manage both scenarios.
The MSIX packaged model is the most powerful one since it gives you access to all the features offered by Microsoft Store. In fact, an MSIX packaged application is hosted directly by the Microsoft infrastructure, which enables all the features highlighted at the beginning of this section regarding deployment, such as a built-in signing process, automatic updates, and gradual rollouts.
To generate an MSIX package for the Store, you can use the Visual Studio wizard that you can trigger by right-clicking on your project and choosing Publish | Create app packages. In the first step, choose Microsoft Store under a new app name. You will be asked to log in with your developer account so that Visual Studio can list all the names you have reserved. Choose the one you have created for your application and continue the wizard, following the steps we described earlier in this chapter.
The outcome will be an unsigned MSIX package (remember that the Store will take care of it for you) and the identity assigned by Partner Center. The package will have a special extension—.msixupload. Now you can navigate to the Packages section of the submission process and upload it. The Store will ingest it and make it available through its platform.
Now, let's see how you can handle unpackaged applications.
In the case of an unpackaged application, the Store will function mainly as a window for your software. Users will still be able to find your application in the catalog, discover information about it, and install it with a single click. However, the application won't be hosted by the Store. Instead, it must be hosted by your own infrastructure, such as a website or cloud storage. Since the Store doesn't handle the distribution, many of the features won't be available since it behaves like a sideloading scenario: you must take care of signing or delivering automatic updates. However, you will still be able to use the monetization services and the feedback system provided by the Store.
Note
At the time of writing, publishing unpackaged applications is in preview. Before getting access to this feature, you must submit your nomination at https://aka.ms/storepreviewwaitlist.
When you choose to publish an unpackaged application, the Packages section of the submission process will be different. Instead of uploading a package, you must provide the following information:
Regardless of the deployment technology you choose, the application will go through a certification process.
Once you submit the application, it won't be immediately available, but it must pass a certification process. The Store will run a series of automated tests that will make sure your application behaves properly: for instance, it doesn't crash at startup, it doesn't contain malicious code, it's reliable, and more. Additionally, your application might also be selected for manual testing, which will validate not only the technical side but the content policies too. In fact, some content isn't allowed in the Store, such as pornography, blasphemy, and the like.
You can review all the policies at https://docs.microsoft.com/en-us/windows/uwp/publish/store-policies.
Once your app has been certified, it's made available to all Windows users. At this point, you will also have the option to submit updates.
To submit an update, you must create a new submission starting from an existing application. The submission process is the same as the one you have followed first the first release, with the difference that all the various steps (for instance, pricing, markets, metadata, and more) will be already filled with the information you have submitted the first time.
The way you submit an updated package changes based on the deployment scenario:
Microsoft Store is a powerful distribution system for consumer applications. However, for enterprise applications, it might not be the best option, since many of the features it provides are tied to the consumer ecosystem. For instance, the payment system is tied to the personal Microsoft account and enterprises are unable to build their own catalog of applications.
For all the other scenarios, you can opt for sideloading distribution from a website, cloud storage, or an internal share.
In the next section, we're going to learn how, thanks to MSIX and AppInstaller, we can retain some of the features that we have seen so far.
If you are building a Windows application, there are many reasons why you might want to distribute your application using a website. If you are an Independent Software Vendor (ISV), you might only need to protect the download of the application to your registered users by using a reserved area on your website; if you are an enterprise, you might build an internal website or an internal network share where employees can download the applications they need.
Of course, if you prefer to use the unpackaged model, you can keep using traditional deployment technologies such as MSI or ClickOnce and add a link on your website to download it. However, thanks to MSIX, you can enable a more streamlined deployment experience using AppInstaller. This enables you to do the following:
AppInstaller is an application included in Windows 10 that enables all these scenarios other than providing the installation experience for MSIX packages. The user experience you see when you double-click on an MSIX package to start the installation is managed by AppInstaller.
Additionally, AppInstaller supports a special file, with the .appinstaller extension, which describes the installation experience of your MSIX package. You can specify the URL where the package can be downloaded, where to download eventual dependencies, such as the Windows App SDK runtime, and how you want to handle updates. This file can be published together with your MSIX package or embedded directly inside it.
Let's see what an AppInstaller file looks like:
<AppInstaller
Version="1.0"
Uri="https://www.contoso.com/ContosoExpenses
.appinstaller "
xmlns="http://schemas.microsoft.com/appx/appinstaller
/2018">
<MainPackage
Name="ContosoExpenses"
Publisher="CN=Matteo Pagani, O=Matteo Pagani, L=Como,
S=Como, C=IT"
Version="1.0.5.0"
ProcessorArchitecture="x86"
Uri="https:\www.contoso.comContosoExpenses.msix" />
<Dependencies>
<Package
Version="0.319.455.0"
Uri="https://www.contoso.com/Microsoft.WindowsApp
Runtime.1.0.msix"
Publisher="CN=Microsoft Corporation, O=Microsoft
Corporation, L=Redmond, S=Washington, C=US"
ProcessorArchitecture="x86"
Name="Microsoft.WindowsAppRuntime.1.0" />
</Dependencies>
<UpdateSettings>
<OnLaunch
HoursBetweenUpdateChecks="0"
ShowPrompt="true" />
</UpdateSettings>
</AppInstaller>
Let's break it down into the main four sections:
Additionally, the AppInstaller file can specify other types of dependencies, such as optional packages (special packages that contain add-ons for the main application) or modification packages (special packages that can customize the existing installation of the application).
The following documentation gives you a detailed overview of the AppInstaller schema and all of the available options: https://docs.microsoft.com/en-us/windows/msix/app-installer/how-to-create-appinstaller-file.
However, there are better ways than having to generate the file manually. Let's explore the options we have next.
Visual Studio can generate an AppInstaller file for you as part of the build process that generates an MSIX package. The starting point is the same wizard we looked at earlier, that is, the one that you can trigger by choosing Publish | Create a package when you right-click on your project.
Note
At the time of writing, this option is only available for the Windows Application Packaging Project. If you're building a WinUI application using the single-project MSIX approach, you will still see the option to generate an AppInstaller file, but it won't have any effect. At the end of the build process, the AppInstaller file will be missing.
When you choose Sideloading as a distribution method, you can also enable a flag called Enable automatic updates, as you can see in the following screenshot:
When you check this option, you will see a new step of the wizard, titled Configure update settings, at the end of the process. It will appear before the creation of the package:
In this step, you must provide the URL of the network share path where you're planning to make your application available and how often Windows should check for updates. Then, you can hit Create to start the creation of the MSIX package.
At the end of the process, in the same folder where Visual Studio has generated the MSIX package, you will also find the following two additional files:
However, this wizard has a limitation: the AppInstaller file has evolved over time by supporting new features such as update prompts or mandatory updates. The wizard didn't follow the same evolution and, as you have seen in Figure 11.9, it doesn't support these new features.
To work around this limitation, you can add an AppInstaller template to your project. This is a special file that will be used as a template during the generation of the package, and it contains placeholders for the key information, such as the installer location or the application's version. During the build process, Visual Studio will replace them with the actual data generated during the build. To add this file, you must right-click on your project and choose Add | New item. Choose the AppInstaller template, leave the default name (Package.appinstaller), and press Add. This is what the file looks like:
<AppInstaller Uri="{AppInstallerUri}"
Version="{Version}"
xmlns="http://schemas.microsoft.com/appx/
appinstaller/2017/2">
<MainPackage Name="{Name}"
Version="{Version}"
Publisher="{Publisher}"
Uri="{MainPackageUri}"/>
<UpdateSettings>
<OnLaunch HoursBetweenUpdateChecks="0"/>
</UpdateSettings>
</AppInstaller>
This is very similar to the file we have seen before, except that most of the information is described with a placeholder and wrapped inside curly braces (such as {AppInstallerUri} or {Publisher}). Being a template, you can customize it as you prefer, for example, by adding new entries and attributes in the UpdateSettings section to enable new features.
Note
Visual Studio generates the AppInstaller template using an old xmlns schema, which doesn't support many of the new features. As such, it's important to replace the current one with the following:
xmlns="http://schemas.microsoft.com/appx/appinstaller/2021"
When you generate a package using the wizard, Visual Studio will use this file as a base template. In fact, in the Configure update setting section of the wizard, you won't be able to customize the settings (other than the location URL) anymore since they will be taken directly from the template.
But what if you want more flexibility when creating an AppInstaller file? Let's explore another option next.
AppInstaller File Builder is an application developed by Microsoft, which is part of the MSIX Toolkit—a series of utilities to support working with MSIX packages. You can download it from https://github.com/microsoft/MSIX-Toolkit/releases/.
You can use this tool to generate an AppInstaller file more easily, thanks to its visual interface:
What makes this a powerful tool is that instead of manually filling in all the required information, you can just click on the Get Package Info button to choose the MSIX package you want to publish from your hard disk. The tool will automatically extract all the information for you. Thanks to this tool, you can define the following:
Once you have filled in all of the information, you can move on to the Summary section. Here, you'll be asked to specify the URL where you're going to publish the AppInstaller file, the URL of the various packages, and the version number:
By clicking on Generate, the tool will generate the AppInstaller file for you, all ready to be used. But how can we use it?
Now that we have an AppInstaller file, all we need to do is deploy it together with our packages (the main one and the eventual dependencies) in the location we have chosen, which can either be an HTTP endpoint or a network share.
Once we have deployed them, we can use one of the following two ways to trigger the installation of the package:
Note
At the time of writing, Microsoft has discovered a vulnerability related to the ms-appinstaller protocol, which is described at https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-43890. For this reason, option 2 isn't currently available, but it might be restored in the future once the vulnerability has been addressed.
Starting from Windows 11, you can also choose to embed the AppInstaller file inside your MSIX package. This doesn't replace the need to publish your AppInstaller file to a website or network share: if you want to deliver automatic updates, you will still need to make it available through an HTTP endpoint. However, by embedding the AppInstaller file inside the package, you can enable automatic updates even if the application has been manually installed the first time; you can do this by directly using the MSIX package rather than the AppInstaller file.
If you want to use this possibility, first, you'll have to copy the same AppInstaller file you previously generated and deployed inside the Visual Studio project. Then, you must declare it in the application's manifest.
First, you'll need to add an extra namespace called uap13:
<Package
xmlns:uap13="http://schemas.microsoft.com/appx
/manifest
/uap/windows10/13" IgnorableNamespaces="uap13">
...
<Package>
Then, inside the Properties section of the manifest, you must add an AppInstaller entry with the path of the AppInstaller file inside the package:
<Properties>
<uap13:AutoUpdate>
<uap13:AppInstaller File="Update.appinstaller" />
</uap13:AutoUpdate>
</Properties>
Now that we have deployed and installed our application via an AppInstaller file, let's see how we can apply updates.
Thanks to the UpdateSettings section, we have added to our AppInstaller file. Now, we can enable automatic updates without having to write any other code in our application. We just need to generate an updated AppInstaller file and MSIX package, making sure that we set a higher version number for both. Then, we need to upload them in the same HTTP or network location where we deployed the original version of the application.
Now, based on the update logic that we have defined in the AppInstaller file, Windows will automatically pick the update and install it. Users won't need to come back to the website or the network share to download and install the package again.
For example, if you are using the OnLaunch configuration and you have enabled the ShowPrompt option, users will see the following message the next time they open your application:
In other scenarios, you might want more granular control over the updates. Let's explore this scenario by using the Package APIs.
After you have deployed an application using AppInstaller, you can leverage which APIs belong to the Windows.Management.Deployment namespace to check for available updates and install them. This approach requires more work since you'll have to write some additional code, but it enables you to further customize the update logic since you are in full control of the update process.
Let's see a code example that we can use to trigger the update:
private async Task CheckUpdatesAsync()
{
PackageManager pm = new PackageManager();
Package package = pm.FindPackageForUser(string.Empty,
Package.Current.Id.FullName);
PackageUpdateAvailabilityResult result = await
package.CheckUpdateAvailabilityAsync();
switch (result.Availability)
{
case PackageUpdateAvailability.Available:
case PackageUpdateAvailability.Required:
var installTask =
pm.AddPackageByAppInstallerFileAsync(
new Uri("https://www.contoso.com/
ContosoExpenses.appinstaller"),
AddPackageByAppInstallerOptions
.ForceTargetAppShutdown, pm.GetDefault
PackageVolume());
installTask.Progress += (installResult,
progress) =>
{
Console.WriteLine(progress);
};
var installResult = await installTask;
if (!installResult.IsRegistered)
{
Console.WriteLine(installResult.ErrorText);
}
break;
case PackageUpdateAvailability.Unknown:
case PackageUpdateAvailability.NoUpdates:
MessageBox.Show("No updates available");
break;
}
}
Here, we use the PackageManager class to retrieve a reference to the current instance of the application by calling the FindPackageForUser() method. As parameters, we must pass the identifier of the user (we can pass an empty string if we want to retrieve the packages for all of the users) and the Package Family Name. Since our application is packaged, we can retrieve it using the Package.Current.Id.FullName property.
Once we have a reference to the package, we can invoke the CheckUpdateAvailabilityAsync() method, which will use the information stored inside the AppInstaller file that we used to install the application, to check whether there's a new update available. If there's indeed a new version, we will get back the Available value or the Required value of the PackageUpdateAvailability enumerator (this depends on whether we marked the update as optional or required). If that's the case, we can move on with the installation process by calling the AddPackageByAppInstallerFileAsync() method of the PackageManager class. This requires the following parameters:
The result of the method is represented by a special Windows Runtime interface called IAsyncOperationWithProgress, which can be used to track the progress of asynchronous operations. In the previous snippet, you can see an example of how you can use it: we don't immediately execute the method, but we just Store a reference to the Task object that represents it (notice how we call the AddPackageByAppInstallerFileAsync() method without prefixing it with the await keyword). Then, we subscribe to the Progress event, which we can use to monitor the progress of the operation.
Following this, we start the task by invoking it with the await prefix. We can use the IsRegistered property of the result to determine whether the operation has been completed successfully; otherwise, we can use the ErrorText and ErrorCode properties to understand what went wrong.
So, what if you have opted to not use the AppInstaller file, but you still want to provide a way to deliver updates? In this case, you can use the AddPackageAsync() method offered by the PackageManager class, directly passing the URL of the updated MSIX package as a parameter. This is shown in the following snippet:
PackageManager packagemanager = new PackageManager();
await packagemanager.AddPackageAsync(new
Uri("https://www.contoso.com/ContosoExpenses.msix")
,null, AddPackageOptions.ForceApplicationShutdown);
Even if this code might look simpler than the AppInstaller scenario, it actually requires more work from your side. In fact, if the application hasn't been installed with an AppInstaller file, Windows doesn't have a way to understand whether there's a new package available. As such, you must implement this logic on your own, for example, by exposing this information through a REST API that you must call before installing the update.
Let's wrap up the AppInstaller overview by taking a quick look at two new features that have been added to Windows 11.
Starting from Windows 11, AppInstaller supports two new features:
The first feature is enabled through the UpdateUri section, which looks like this:
<UpdateUris>
<UpdateUri>https://www.contosobackup.com/
ContosoExpenses.AppInstaller</UpdateUri>
<UpdateUri>\MyNetworkShare\ContosoExpenses
.AppInstaller</UpdateUri>
</UpdateUris>
The second one is enabled by the RepairUris section, which is defined as follows:
<RepairUris>
<RepairUri>https://www.contosobackup.com/
ContosoExpenses.AppInstaller</RepairUri>
<RepairUri>\MyNetworkShare\ContosoExpenses.
AppInstaller </RepairUri>
</RepairUris>
We have completed the exploration of another way to distribute our Windows applications. This is via a website or a network share, which is a scenario made easier by MSIX and AppInstaller. Now, let's see the last option we're going to discuss in this chapter: Windows Package Manager.
Installing applications can be a long and tedious process, especially if you're building a new machine and you have to reinstall all the tools you need for your work and personal file. What if you could somehow automate this process? What if you can make it faster rather than having to pick the applications you need one by one? These are the reasons that led Microsoft to create a new utility called Windows Package Manager (the short name is winget), which is inspired by other popular tools such as Advanced Package Tool (APT) and Chocolatey.
Note
Windows Package Manager is deployed through the AppInstaller application, which is built inside Windows. As such, you will find this utility already available on every Windows installation starting from Windows 10 1709. Preliminary versions of the new releases are available through the official GitHub repository at https://github.com/microsoft/winget-cli/releases.
Windows Package Manager is a command-line tool that you can use to quickly install and upgrade applications on your machine from a variety of sources, such as websites and Microsoft Store. The tool is backed up by a repository, which is hosted on GitHub at https://github.com/microsoft/winget-pkgs. It contains a manifest for each available application. The manifest is a YAML file that describes the application, including the URL where it can be downloaded from. For example, this is an excerpt of the manifest of Microsoft Edge—the popular Microsoft browser:
# yaml-language-server: $schema=https://aka.ms/winget-
manifest.singleton.1.0.0.schema.json
PackageIdentifier: Microsoft.Edge
Publisher: Microsoft
PackageName: Microsoft Edge
Author: Microsoft
ShortDescription: World-class performance with more
privacy, more productivity, and more value while you
browse.
Moniker: msedge
Tags:
…
MinimumOSVersion: 10.0.0.0
PackageVersion: 86.0.622.38
InstallerType: msi
Installers:
- Architecture: x64
InstallerUrl: https://msedge.sf.dl.delivery.mp
.microsoft.com/filestreamingservice/files/53a5f508-
44da-4f9d-85d9-312fb8f92f4b/MicrosoftEdge
EnterpriseX64.msi
InstallerSha256: D49104F182675701423CB774
CD2120B3A3FF63565661E4364D1169F64B9019EC
Scope: machine
PackageLocale: en-US
ManifestType: singleton
ManifestVersion: 1.0.0
The key information elements in the manifest are as follows:
If you want to install this application, you just need to open a Command Prompt or Windows Terminal and type in the following command:
winget install Microsoft.Edge
Windows Package Manager will display a progress bar, and it will let you know when the application has been installed. Thanks to winget, you can manage the full life cycle of the application. For example, you can use the following command to update Edge:
winget upgrade -q Microsoft.Edge
Also, you can use winget to remove an application by invoking the following command:
winget uninstall Microsoft.Edge
As a user, the whole winget backend is completely transparent. You don't have to know how and where manifests are stored. In fact, you can directly search whether an application is in the catalog with the search command, as shown in the following example:
winget search edge
The tool will give you a list of packages that matches the criteria and their identifiers so that you can install the one you're looking for, as shown in the following screenshot:
As a developer, making your application available through Windows Package Manager is a worthwhile investment since the following can occur:
In the next section, let's see how we can create a manifest.
As mentioned earlier, a manifest is just a YAML file that contains the metadata of the application. As such, you could create it manually with any text editor by following the schema described at https://docs.microsoft.com/en-us/windows/package-manager/package/manifest.
However, Microsoft provides a command-line tool that you can use to generate and update manifests more easily. The tool is called WinGetCreate, and guess what? It's available through Windows Package Manager. To install it, just open a Terminal and run the following command:
winget install wingetcreate
Once the installation is complete, you can start the creation of a new manifest by calling the following command:
wingetcreate new
A wizard will guide you through the flow so that you can specify the following information:
The tool will automatically generate the manifest file in a path that follows the same rule adopted by the official repository, which is as follows:
manifests<first letter of the publisher><name of the
publisher><name of the application><version number>
For example, if you explore the official repository on GitHub, you will find that the Microsoft Edge manifest is stored in the following path:
ManifestsmMicrosoftEdge86.0.622.38Microsoft.Edge.yaml
Once the manifest has been generated, the tool will give you the option to submit it to the Windows Package Manager repository. This is so that your application can be made available in the catalog. If you have created the manifest manually, you can validate it before submitting it, to make sure you haven't made any mistakes, by using the following command:
winget validate <path of the YAML file>
Regardless of the way you have created the manifest, to submit it, the wingetcreate tool will first ask you to log in to GitHub with your account.
The mechanism behind the manifest submission is the Pull Request. Once the manifest has been submitted, you will find a new pull request in the Windows Package Manager Community repository, which will add the manifest you have just created to the catalog. The pull request will trigger a validation process, which will verify that the metadata is correct, the installer URL is valid, the binaries are safe, and more. Once the pull request has been approved, the new manifest will be merged inside the main repository, and you'll be able to start using the winget install command to install your application.
The wincreate tool can also be used to create an update for an existing manifest and submit it to the repository, as shown in the following example:
wingetcreate update MatteoPagani.ContosoExpenses -v
1.0.201.0 -u https://www.contoso.com/ContosoExpenses
102010.msix
Unlike the create option, the updated one isn't interactive, which makes it a good fit to be integrated inside a CI/CD pipeline. We'll learn more about this scenario in Chapter 12, Enabling CI/CD for Your Windows Applications.
Finding the right technology and platform to distribute your application is essential for building a successful product. However, once the application has been installed, your work as a developer doesn't stop there: you must manage the licensing, the monetization, the feedback, and the automatic updates. All of these tasks are equally important to continuously deliver value to your users.
In this chapter, we have explored some of the technologies (such as MSIX) and the platforms (such as Microsoft Store, sideloading with AppInstaller and Windows Package Manager) that you can use to plan a successful deployment and, at the same time, simplify many of the challenges that you face as a developer. Examples of this include setting up automatic updates with AppInstaller, delivering a clean and reliable clean installation and uninstallation experience with MSIX, and more.
This chapter serves as a foundation for the next and concluding chapter: we're going to see how, thanks to the technologies we have learned, we'll be able to automate building and deploying our Windows desktop application, thanks to the adoption of DevOps best practices.
18.223.170.223