Automatic .appx build with project centennial

Let’s say you are creating or already have a legacy windows app (Win32, .NET, …) but want to use all the benefits of UWP platform such as store distribution, clean (un)install, and a few more. Luckily for you there’s a way to do it starting with Anniversary Update. You can convert any legacy app either manually or with a Destkop App Converor to an .AppX package and enjoy all the UWP goodies.

While the packaging process itself is documented quite quite well it’s acutally rather tricky to automate and integrate it into a build process. But before we get to that I’ll share some notes on creating the files required for manual conversion.

  1. Files map should contain paths relative to the place the final packaging script is going to be invoked from.
  2. Certain things such as extension registration or automatic on-windows-startup launch can be done via AppX manifest extensions documented here.
  3. Following xml schemas will surely be useful:

Ok, let’s say we have the AppX manifest, files map, and certificates for self-signing ready and just want to automate and integrate the packaging into the build system.

  1. Create a packaging .bat script:
rem Prepare folders for build:
if not exist "..\Build" mkdir ..\Build
if not exist "..\Build\Appx" mkdir ..\Build\Appx

rem Package AppX using mapping file (contains paths to executables, app manifest, ...)
MakeAppx pack /o /f MappingFile.txt /p ..\Build\Appx\PowerSwitcher.appx
rem Sign the AppX using self-signed certificate
signtool.exe sign -f ..\Build\Certs\my.pfx -fd SHA256 -v ..\Build\Appx\PowerSwitcher.appx
  1. Create a new Build configuration based on Release named e.g. ReleaseAndPackage
  2. Edit .csproj and add following lines that set build variables for paths to signtool.exe and MakeAppx.exe:
    <WindowsKitsRoot>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot10', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>
    <WindowsKitsRoot Condition="'$(WindowsKitsRoot)' == ''">$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot>
    <WindowsSDKTools Condition=" '$(WindowsSDKTools)' == '' And '$(Platform)' == 'AnyCPU' ">$(WindowsKitsRoot)bin\x64\</WindowsSDKTools>
    <WindowsSDKTools Condition="'$(WindowsSDKTools)' == ''">$(WindowsKitsRoot)bin\$(Platform)\</WindowsSDKTools>

4) Go to Build Events properties of ReleaseAndPackage configuration and add following to Post-build. It first adds the variable from 3) to path, checks ConfigurationName, and if all is correct launches the package script from 1).

PATH %PATH%$(WindowsSDKTools);
if "$(ConfigurationName)" == "ReleaseAndPackage" (
cd $(SolutionDir)PowerSwitcher.Appx
Written by on