advanced MSI packaging

YOU’RE READING

MSIX Packaging Fundamentals

by Tim Mangan, Bogdan Mitrache & Kevin Kaminski

Download ebook

Winget Guide: Windows Package Manager for MSIX Packaging | Advanced Installer

What is Winget: Introduction and Origins of Winget

The Windows Package Manager (Winget) is a free and open-source command-line tool designed by Microsoft for Windows 10 and Windows 11. Announced in May 2020 and officially released in version 1.0 on May 27, 2021, its primary goal is to simplify installing, updating, and managing software on Windows systems. The long-standing success of package managers in the Linux ecosystem influenced the development of Winget.

Microsoft decided to develop Winget after exploring existing Windows package managers like Chocolatey, Scoop, Ninite, AppGet, Npackd, and OneGet. Notably, the development process was not without controversy, with Kyivan Beigi, the developer of AppGet, alleging that Microsoft engaged with him and drew inspiration from AppGet. Later, Microsoft acknowledged the inspiration and gave credit.

The creation of Winget aligns with a broader trend in the computing world towards centralized and automated software distribution, inspired by the efficiency and security demonstrated by Linux package managers like APT, YUM/DNF, Pacman, and Zypper.

Package management began as a solution to streamline software installation and manage dependencies on Linux. It has evolved into a rich tool ecosystem that spans multiple platforms, including Windows. Every operating system has multiple package managers available, each with its own features and behaviors.

Dimitrius Nelon is credited as the founding developer of Winget. Being open-source under the MIT license and hosted on GitHub, Winget actively engages with the community for bug reporting and feature feedback, notably influencing the prioritization of Windows Server 2025 support.

Though Microsoft had many avenues to use for a package manager, the reasoning was to build an open-source solution that Microsoft could influence for its needs, which were the new Windows Store and modern application support. Not everyone agreed with the approach, as it was seen by some as yet another package manager.

Key Use Cases and Benefits of Winget

Winget offers several significant advantages for Windows users and administrators:

- Easy Software Installation: Winget enables quick application installation using command-line instructions, eliminating manual downloads. Users can quickly search for and install applications using simple command-line instructions, eliminating the need to download installers from websites manually.

With Winget, users can install, upgrade, or remove applications using simple commands. For example:

winget install --id Microsoft.VisualStudioCode

On the first run, I have to agree to the license terms of the default repository it will use to get the application. Press Y, then enter to agree to the license terms.

Administrator Command Prompt

The application is then installed.

the application is the installed

- Automated Updates: This feature simplifies checking for and applying updates to installed software, enhancing system security and currency. Users can easily check for and apply updates to installed software, ensuring systems remain current and secure.

- Trusted Package Discovery: This tool helps users discover new and popular applications through its extensive repository.

- Version Management: Winget supports installing specific software versions and managing multiple versions when needed.

- Scripting and Automation: Can be integrated into scripts and automated processes for software deployment. As a command-line tool or using the PowerShell module, winget can be integrated into scripts and automated software deployment and management processes.

- Consistent Environment Setup: Allows exporting and importing lists of installed packages for consistency across systems. Users can export lists of installed packages and import them on other systems, ensuring consistency across multiple machines.

- Custom Software Distribution: Enables organizations to create custom manifests for internal software management. Organizations can create custom manifests for in-house software, allowing for centralized management of proprietary tools.

- Simplified Portable App Management: Winget adds entries for portable executables to the Control Panel, making them easier to track and manage.

Winget draws direct inspiration from Linux package managers' key benefits, such as dependency management, enhanced security through trusted repositories, ease of updates, and streamlined software discovery.

Key Benefits of Package Managers:

  • Dependency Management: Package managers automatically resolve software dependencies, installing all necessary libraries and files.
  • Security and Trust: Software is typically signed and vetted by the distribution maintainers, reducing the risk of malicious code.
  • Ease of Updates: Centralized repositories allow quick updates and security patches, often with a single command.
  • Streamlined Software Discovery: With searchable repositories, users can easily find and install the software they need without hunting for external downloads.

Integration with Windows and Modern Application Formats

A primary driver for Winget's creation was managing modern application formats like MSIX. Its seamless integration with the Windows ecosystem and familiar command-line interface aims to bridge the gap for users accustomed to Linux package managers.

One of the main reasons for creating Winget was to have a package manager that supports modern application formats. Winget is built for the Windows ecosystem, integrating smoothly with the command line and Intune. It provides a familiar command-line interface that echoes the experience of Linux users, bridging the gap between the two worlds while allowing system administrators to acquire applications easily through the Windows store.

Security is a key priority for Winget, with applications sourced from trusted repositories maintained by Microsoft. Microsoft also keeps the tool adhering to enterprise-grade security standards. Microsoft uses Repology to audit the Winget manifest repository for outdated applications, adding transparency.

Much like Linux package managers, Winget prioritizes security. Applications available via Winget come from trusted sources, and Microsoft maintains the tool, ensuring it meets enterprise-grade security standards. Microsoft also audits the repository with Repology to clarify which applications in the Winget manifest repository are outdated.

Winget's adoption of community contributions through third-party repositories and packages mirrors the collaborative nature of many Linux distributions, fostering a growing ecosystem of available applications.

Winget has also embraced community contributions. Allowing third-party repositories and packages mirrors the collaborative spirit seen in many Linux distributions. This open model encourages developers to package their applications for easier distribution, further expanding the ecosystem.

Winget Concepts

Winget Repositories

A winget repository is a collection of software packages that can be installed, updated, and managed using the Windows Package Manager (winget). It is a centralized location where application manifests (metadata about software packages) are stored and made available for users. This location is important as the installation files for the application may reside on a separate internal server or on the Internet.

The following diagram outlines the conceptual design of winget and repositories.

diagrame winget concepts

You will notice that there are many options for where you can host your applications but keep in mind if you are using Intune, then you are limited to the available Store applications. Winget is currently the most flexible at the command line regarding where you can consume your applications. Let’s look at repositories in more detail.

Repository Types

- Official winget Repository (Community Repository)

Hosted by Microsoft at https://github.com/microsoft/winget-pkgs, winget manifest files are free to browse and copy. It contains thousands of applications the community contributes, and most are regularly updated. Microsoft moderates and extensively validates submitted packages before adding them to the repository for distribution.

Applications published through the Windows Store should be submitted using a developer account with the Microsoft Partner Center. This does involve a registration fee for the developer, but this method gets the application into the Store, which allows Intune administrators to distribute it.

- Third-Party:

Some repositories are public but not Microsoft-managed and have a catalog of applications that can be used. Some examples are:

- Private Winget Repositories:

Organizations can create and manage their own private repositories to distribute internal or approved applications, but this is not easy. Microsoft has updated its solution on GitHub (https://github.com/microsoft/winget-cli-restsource) or possibly looked into third-party solutions such as Winget.Pro. Customers often complain about not having a Microsoft solution for this scenario.

While it is helpful for enterprise environments to control software installations and updates, setting it up is complex. Other methods include a static web server, but the file structure must be manually updated in an SDB and sealed in a signed MSIX file.

Turning off security features for running specific manifest files is useful for testing, but overall, turning off security for manifests isn’t ideal. Consider putting in the effort to build your repository where you control the packages available. This is especially important with upgrades because expecting winget to upgrade all software without issue is a big ask, as the underlying software installers may run into problems and need testing with possible remediation.

Let’s look at the winget package files in more detail to better understand what winget does.

Manifest Files

What may seem initially strange is that the files used to control the installation likely are not in the exact location as the installation binaries. This is especially true with the public Winget repositories, as they only host the manifest files for packages, and the files reside elsewhere.

Typically, a package has the following manifest files:

  • Installer.yaml – Defines the installer file, architecture, installation command, and other metadata.
  • Version.yaml – Specifies version information.
  • Locale.yaml(optional) – Defines localized metadata about the installation.

Generally, the file of most interest is the Installer.yaml as it contains much information about the actual software installation process. For example, look at the following file.

PackageIdentifier: Mozilla.Firefox.ESR.MSIX (must be unique)
PackageVersion: 128.8.0 (must be unique)
MinimumOSVersion: 10.0.17763.0
InstallerType: msix (must be specified)
Protocols:
- http
- https
- mailto
FileExtensions:
- avif
- htm
- html
- pdf
- shtml
- svg
- webp
- xht
- xhtml
PackageFamilyName: Mozilla.MozillaFirefox_jag0gd4e3s9p2
ReleaseDate: 2025-03-04
Installers:
- Architecture: x86
  InstallerUrl: https://download-installer.cdn.mozilla.net/pub/firefox/releases/128.8.0esr/win32/multi/Firefox%20Setup%20128.8.0esr.msix
  InstallerSha256: 1CD459EF66C4FE84F4589AE0D6384FF894AE740C6ABD9B9CF7873C13D494CD5C
  SignatureSha256: 637F6AD299EEB0D575D28AC50179D21765A0E0BF89EC9148D98C64FB879D3AD1
- Architecture: x64
  InstallerUrl: https://download-installer.cdn.mozilla.net/pub/firefox/releases/128.8.0esr/win64/multi/Firefox%20Setup%20128.8.0esr.msix
  InstallerSha256: 632FC56139229F1620227151C3168C1B501E72670CDBCB1001E37F7BBE721582
  SignatureSha256: DE7B1F1815342606820403973FE9DB438F578074C28A6F1EB1C9F358E54A5409
ManifestType: installer
ManifestVersion: 1.9.0

The requirements contain some interesting information. Generally, the most important fields to get right are the PackageIdentifier and PackageVersion fields. The good thing is that you don’t need to build the files by hand, but not every possible piece of metadata is automatically created with the winget packaging tools. It is good to see what other vendors are doing to better understand what might suit your YAML files.

Winget Settings

To view my current winget configuration, I need to run the following command. I do recommend having a JSON editor configured ahead of time to make the modification process easier. The key thing is that these JSON files can be customized and shared to change the default behavior of the winget application.

To view the current settings, simply run the following:

winget settings

Winget will then open a settings.json file with whatever Windows has set as the default handler for file types. Currently, this settings.json is commented out, but more importantly, you can see where the settings.json file is located. The winget engine, known as the DesktopInstaller app, is where the settings reside on a per-user basis.

C:\Users\<UserName>\AppData\Local\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\settings.json

You should notice that even after customizing the settings.json, the winget settings command will open a template settings file, not the complete settings configured on the device.

For validation of the settings.json, it is recommended to run the command winget settings, but you will look at the window where the command is run and see the output.

For example, this JSON has an issue with where the scope setting was placed.

json issue with the scope

When I looked at the JSON schema, I had a better idea of where to place my settings in the JSON file, so I recommend that you use this resource when troubleshooting issues with the settings.json file.

https://aka.ms/winget-settings.schema.json

You can also use this heavily customized settings.json as an initial reference.

MSIXFundementals2025/Winget Settings Files/Complete Settings Examples/settings.json at main · kkaminsk/MSIXFundementals2025

{
    "$schema": "https://aka.ms/winget-settings.schema.json",
"downloadBehavior": {
        "defaultDownloadDirectory": "C:/Windows/Temp"
    },
"telemetry": {
    "disable": true
},
"source": {
    "autoUpdateIntervalInMinutes": 0
},
"logging": {
    "level": "verbose"
},
"installBehavior": {
    "preferences": {
        "locale": [ "en-US", "en-CA" ],
        "scope": "system",
        "installerTypes": ["msix"],
        "architectures": ["x64"],
    }
}
}

In the example above, we can see some customizations.

defaultDownloadDirectory = Sets the download directory to where installers are downloaded before installation.

telemetry = Microsoft uses telemetry data to improve WinGet by collecting telemetry from Winget such as usage statistics, errors, and performance data.

source = 0 - Automatic updates are disable by default.

logging = level - Verbose will log all event types. Log levels include.

  • Verbose (all)
  • Info (default)
  • Warning
  • Error
  • Critical

The default location is: %LOCALAPPDATA%\Microsoft\WinGet\Logs

The log location can be reconfigured with the logFolder setting.

installBehavior

preferences

  • locale - Language preference.
  • installertypes - Preferred installer format for the application.
  • architectures - The preferred application architecture.
  • scope - When installing the application, does it install per-machine or per-user

Tip: Exporting the settings can also be done to a more convenient location; consider the following command:

winget settings export > C:\winget-settings.json

Using Winget

Command Line Winget

Winget has started off as a command-line tool and so that leads us to begin with using winget in the context of a command prompt. To start using winget, it is good to start with the following command:

winget search notepad

Using this command, I can search the repositories connected to this device for a specific application. In the above example, we will see what results we get below. First off, we can see that Windows Notepad is on the list, but its application ID is an identifier, which means it is a modern app. Below, we see other installers listed.

Coomand Line Winget

The ID field is important because asking for an application by name isn’t always going to resolve without further information. For example, if I try to run:

winget install --name notepad

The system will return the following error to me, indicating Multiple packages found matching input criteria.

Command line winget Error multiple packages found matching input criteria

Another example might be Firefox. If I run the following command

winget install --name firefox

This command will install Firefox.

Command Line Winget Install Firefox

But if you search winget you will see that there are in fact many different packages to install.

Command Line Winget Different packages to install

What happened is winget selected what it thought was the most appropriate installation for my device. I can then verify the installed package using the following command.

winget list --name firefox

We can see that the browser was installed from the store.

Command Line winget mozzila

See supporting files here:

MSIXFundementals2025/Winget Commands at main · kkaminsk/MSIXFundementals2025

Making Manifest Files

To simplify the process, we will use a tool called WinGetCreate to produce a manifest file. We will use

winget install wingetcreate

You will notice that this package installs two dependencies, as well as WinGetCreate.

Making manifest files Wingetcreate

Before we run WinGetCreate, ensure the application files are on a file or web server (with a certificate) so that winget can download them when needed. I will use the MSIX package for Firefox x64 ESR V128.8.0 for this example. I will use the following download location to make my manifest.

https://download-installer.cdn.mozilla.net/pub/firefox/releases/128.8.0esr/win64/multi/Firefox%20Setup%20128.8.0esr.msix

Next I will run the following:

wingetcreate new

Making Manifet files Winget create new

And I’ll have to put in the URL for the MSIX package and press enter.

Wingetcreate will then inspect the package and ask a series of questions. Press enter to accept the PackageIdentifier suggested value.

Making manifes Files PackageIentifier

Accept the suggested version and press enter.

Making Manifest files Accept Suggested

Press enter to use the suggested locale.

Making Manifest Files use suggeste locale

Press enter to use the suggested publisher.

Making manifest Files Suggested publisher

To define the packagename simply click enter to accept the suggested value.

Making Manifest File define packagename

For the license, put MPL for Mozzila Public License and press enter.

Making Manifest file for the license

Press enter to put in the short description for the package.

Making Manifest Files shortdescription

For the optional locale fields, press N, then return.

Making Manifest File Optional locale fields pres N

For the optional installer fields, press N, then return.

Making Manifest Files Optional Installer fields

To end the editing process, press N and then return.

Making Manifes Files Editing Process

We will not submit the package to Microsoft, so click N and then return.

Making Manifest Files we will nost submit the package

The process is done, but what now?

Making Manifest Files Skipping Pull request

You will notice that the tool creates a manifest folder and folder structure with your YAML files. If you were using a private repository, you would likely copy the folder structure as is. Obviously, storing the files off the root of system32 is not ideal, and you will have to pay attention to your current working directory with elevated command prompts.

If I try to install the manifest directly using:

winget install --manifest <manfiest>.installer.yaml

Making Manifest Files Winget Install

You will see that this is disallowed by default because having the manifest files on a trustworthy source is part of the security model. The repository is a place of trust used to find and install software. This is especially important as tracking an application's vendor installer binaries becomes more challenging when finding software on the Internet.

For testing, I can run the following:

winget settings --enable LocalManifestFiles

Making Manifest Files winget settings

If you specify the installer.yaml file directly in the command like I did you may run into the following error.

An unexpected error occurred while executing the command:

0x8a150004 : Opening manifest failed

Making Manifest Files Unexpected Error

When you specify a folder with multiple YAML files, try to specify the folder rather than the file. In this example, I use .\ as the current working directory.

winget install --manifest .\

Making Manifest Files Winget Installer Manifest

Firefox is now installed on my test machine.

Making Manifest File Firefox installation

Something that isn’t quite explicit but that you must be very aware of is that your installer must be signed. This is used to validate the installer’s authenticity before it is used in the application installation process. You can turn this feature off, but having application installers signed with a code signing certificate is becoming increasingly commonplace to establish reputation and trust with application code and installers.

Find the supporting files over here.

MSIXFundementals2025/WingetCreate at main · kkaminsk/MSIXFundementals2025

Winget and PowerShell

Believe it or not, PowerShell support was not quite production-ready in the early days of Winget. Through community feedback, this feature has evolved quite a bit, allowing for better integration with PowerShell scripting and providing data such as installed packages in a more structured fashion than through the command prompt.

To install the PowerShell Module open a PowerShell prompt as an administrator and run:

Install-Module -Name Microsoft.WinGet.Client

Press Y, then enter.

Making Manifest File Press Y

Next run:

Import-Module Microsoft.WinGet.Client

To view the commands capable of the module, you can use the following command.

(Get-Module microsoft.winget.client).ExportedCommands

Winget and Powershell get-module

For example, to install a package, I would run the following:

Install-WinGetPackage -Id RARLab.WinRAR

Using that command, you should see an output similar to this.

Winget and Powershell output command

As you can see, information like the exit code and reboot requirement are easily exposed so that the script can handle these events.

Winget and the Windows Store

Winget largely works in the background when being used with the Windows Store. In a company setting, IT administrators use Intune to manage applications and they can provision these applications through the Windows Store.

For example, if I go to https://intune.microsoft.com and log into my tenant. I can click Applications, Windows apps + Add then Select App Type. Select the application of the Microsoft Store app (new).

Winget and the windows store - add seleted apps

Click Select.

Winget and Microsoft Store Select app type

Next, go and select Search the Microsoft Store app (new).

Winget and Microsoft Store Select Search

First, search for VLC, and you will notice that two application types are available. Win32 apps are experimental at this point, and not everything in the GitHub repository is available in the store. Usually, Win32 apps are the preference from a functionality standpoint, but modern apps are improving with their support for missing functionality.

For this example, we will select the UWP version of the application to distribute. When using Intune in this fashion, the application will benefit from Delivery Optimization if enabled and configured on your Windows Device. Click Select to proceed.

Winget and Microsoft Store Search the store

For the most part, the application is filled out, but if you scroll down, you will notice that the logo or icon for the application is missing, which can be an issue with self-service applications in the application portal. Go to https://images.google.com to find a suitable png or jpg logo.

Click Select Image when ready.

Winget and Microsoft Store Select Image

Click the folder icon.

Winget and Microsoft Store Logo

Select vlc.jpg then click Open.

Winget and Microsoft Store select vlc

Click OK.

Winget and Microsoft Store select vlc logo

Click Next.

Winget and Microsoft Store select vlc logo next

Under the section Available for enrolled devices, click Add group.

Winget and Microsoft Store Add group

I am going to search for a virtual machine security group in Entra that I have for testing machines. When I find the group, I select the checkbox beside i,t and it will appear to the right. Click Select to continue.

Winget and Microsoft Store Select Groups

Click Next to continue.

Winget and Microsoft Store Select groups next

Click Create to build the application.

Winget and Microsoft Store Select groups create

In the notification area, you will get a notification that the application has been created.

Winget and Microsoft Store Select groups create Notifications

Usually what I recommend is having the Company Portal installed on test devices so the user can test on demand using the following method. If I log into a test virtual machine and open the Company Portal application, I can select the VLC application.

Winget and Microsoft Store Select groups see the VLC.

I can then select Install to test the application.

Winget and Microsoft Store Select groups see the VLC videolan

You may notice some notifications in the bottom right corner. When the installation is complete you will notice in the top right corner of the Company Portal application the Installed status.

Winget and Microsoft Store Select groups see the VLC installed

This deployment infrastructure is probably the best way to deploy your modern app to an organization but this requires a store submission process and might not be the most suitable route when you don’t necessarily want your application to be in a public store.

Another consideration to be aware of is updates. When using this method to deploy applications, the updates are in the vendor’s hands, not the customers’. The old world of locked-down configurations for stability directly clashes with the fluid nature of modern development and release practices, where we live in a world of constant updates.

Logging

Currently, logging is in a tricky location with text logs residing in the following folder.

"%LOCALAPPDATA%\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\DiagOutputDir\"

Running the following command will also open the folder:

winget --logs

In this folder, you will find different logs:

  • WinGet logs: General operating information for the winget application.
  • Winget COM logs: Various core component activities of winget. You can even catch winget being loaded by the system from "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_1.25.300.0_x64__8wekyb3d8bbwe\WindowsPackageManagerServer.exe".
  • Installer logs, sometimes but not always, the applications installers for legacy application formats may put their logs here. Unfortunately, this is yet another place to log for installer logs, but it is important to note that some winget packages may put specific logging information here.

winget install --id firedaemon.openssl --verbose-logs

The examples from this section can be found over here.

MSIXFundementals2025/WingetLogs at main · kkaminsk/MSIXFundementals2025

Current Limitations

Despite its advancements, Winget currently faces certain limitations:

- Lack of Official Configuration Manager Support: Winget's command-line nature differs from Configuration Manager's local system approach to software installation. Configuration Manager is not officially supported. Winget offers command-line application management but wasn’t designed to run as a local system as the Configuration Manager does when installing software.

- Limited Microsoft Solution for Private Repositories: While a GitHub-based solution exists, it requires some skill to deploy to your environment, and other private repository solutions require significant implementation effort. Ideally, you want to use a repository with a RestAPI as that has the best security. Other repository architectures exist, but they have very hands-on manual processes for updating the repository, which isn’t ideal for DevOps or something that needs regular updates. If you plan to use a private repository, be aware that this functionality is not built into Configuration Manager or Intune and must be done via client scripting if you wish to take that approach.

- Absence of Private Apps in Microsoft Store: Unlike the public GitHub library and Microsoft Store integration, there isn't a direct equivalent of a private store for organizations to publish internal applications. Despite integration with the public library on GitHub and the Microsoft Store, there is no Windows equivalent of a private store where a developer could publish line-of-business applications to your organization.

Closing Thoughts On Winget

Winget represents a significant step in the evolution of software distribution and management on Windows, drawing valuable lessons from the mature Linux package management ecosystem. Its focus on simplicity, automation, security, and community collaboration positions it as a vital tool for modern Windows environments. While current limitations exist, ongoing development and alignment with community needs promise a future where Winget will play an even more critical role in streamlining software management for individual users and IT professionals. The trend towards unified experiences, improved security, enhanced productivity, and community-driven growth in package management underscores its increasing importance in the broader software industry.

advanced MSI packaging

YOU’RE READING

MSIX Packaging Fundamentals

by Tim Mangan, Bogdan Mitrache & Kevin Kaminski

Download ebook