The MSIX orb is the first “Windows-only” orb from CircleCI. When Microsoft approached us with the opportunity to build an orb that would help Windows developers build on our platform, we were enthusiastic. Most of our orbs, and general workload, revolve around Linux and utilize Bash. However, we recognized the deep need to provide good CI/CD solutions for building applications on Windows, and with use of PowerShell growing steadily within Linux, it was time to take the plunge.

The MSIX orb has two distinct methods to build the new MSIX/Appx installer format: using Visual Studio and creating the files manually. The Visual Studio solution file is a project setup within Visual Studio that links to other Visual Studio projects and contains the configuration necessary to build the installer package with the correct metadata. This is the most straightforward way of getting up and running with this orb and technology. The manual option is more cumbersome because it involves creating the necessary metadata and mapping files to properly package up a precompiled binary.

In this tutorial, we will cover building packages using a Visual Studio solution file and provide some resources for the manual approach at the end.

What you need to know about code signing

Code signing allows users and operating systems to verify the author of a particular binary or bit of code. It is not immediately obvious whether something is signed, so it is common for operating systems to warn of unsigned binaries. Depending on your system, you may also be warned about unsigned packages and apps. The warning prompts you to confirm that you want to proceed with installing or using that particular package.

Code signing is a required step for MSIX and Appx packages. It usually involves either a costly but widely trusted certificate or a smaller locally created certificate. A locally created certificate may be untrusted unless it is explicitly installed. For this tutorial, we will be using a smaller, locally created certificate, for two reasons:

  • It is not good practice to upload the private portion of a widely trusted private certificate.
  • Locally created certificates are easier to obtain and use for testing.

While there are secure methods of doing so, the most common recommendation for private certificates is to either opt for a trusted, dedicated service or keep it off the internet entirely. The locally created certificate is self-signed and will not be a major incident if it is leaked or obtained by a third party.

You can follow the steps for generating a self-signed certificate in Microsoft’s documentation. After you create it, export the certificate using the instructions available from the same link. We will need to upload the exported certificate to CircleCI.

Our next step is to get the certificate into a text-based format, because environment variables are explicitly text. We can use base64 encoding to do this. Think of base64 encoding and decoding as dehydrating food, and later re-hydrating it. This encoding preserves the file contents while also treating it as text. It can be decoded later when we need the original file.

Use this PowerShell snippet:

[Convert]::ToBase64String([IO.File]::ReadAllBytes($FileName))

Replace $FileName with the name of your exported certificate file. This snippet returns a string you can add to a CircleCI context. You will use this later on in your pipeline. Name this MSIX_SIGNING_CERTIFICATE.

You also need to add the password you used to export the certificate to the same secure context. Because this certificate is for testing purposes only, you do not need to worry about it being compromised as long as it is not installed on any other machines. Name this MSIX_CERTIFICATE_PASSWORD.

Using the MSIX orb

The MSIX orb greatly simplifies building solution-based projects. This minimalist configuration should be enough to get you going:

# .circleci/config.yml
version: 2.1

orbs:
  # We pin the minor version but leave out the patch version
  # to automatically accept non-breaking improvements.
  msix: circleci/microsoft-msix@1.1
  # Gives us easy access to Windows execution environments.
  win: circleci/windows@2.4.0
jobs:
  using-sln:
    executor:
      name: win/default
    steps:
      - checkout
      - msix/pack

workflows:
  demo:
    jobs:
      - using-sln

The msix/pack command takes your .sln project and builds it, bringing in your signing certificate automatically. It publishes the final result as a CircleCI artifact that you can download and verify manually. There are a few parameters available if you need to tweak the behavior, but we have determined the best defaults for most cases.

Because this is a command, you can also reuse the produced file, by saving it to a workspace or uploading it to your own artifact server.

Building MSIX without using Visual Studio

It is possible to use an existing executable, built through other means, with the MSIX executable format. However, it requires manual creation of metadata, which you can learn more about in Microsoft’s documentation.

There are a few key differences in the configuration when you use this approach:

  • You will need to manually define manifest and mapping files, because there is no standard filename for either.
  • Your installer will need to be manually signed using the msix/sign command.
version: 2.1

orbs:
  msix: circleci/microsoft-msix@1.0
  win: circleci/windows@2.4.0
jobs:
  using-sln:
    executor:
      name: win/default
    steps:
      - checkout
      - msix/pack:
          using-sln: false
          mapping-file: mapping.txt
          manifest-file: appxmanifest.xml
      - msix/sign:
          import-cert: true

workflows:
  build:
    jobs:
      - using-sln

In this snippet, packaging a non-Visual Studio solution project is a little more manual, but it is supported by the orb.

For both approaches, there are some resources available in the orb source repository. These resources are primarily used for integration testing, but they also demonstrate the capabilities of the orb.

Going forward with building for Windows using CircleCI

My fellow engineers and I have been very happy with the experience of working with PowerShell for scripting. For us, it has proven to be more robust by default than Bash. Our team is satisfied with the end result of the MSIX orb and we hope your and your team find it useful. It is not a universal execution environment, so we do not rely on it for other orbs. However, we continue to invest time into it and hope to build more orbs with better native support for Windows executors. We are dedicated to improving the experience for teams building for the Windows OS on our platform.