apulSoft Blog

Aug 21st, 2024 - Windows WiX

Windows .msi Plugin Installer using WiX v5


Motivation

The Windows installers of all apulSoft plugins have been done using Inno Setup for many years. It is easy-to-use and free. Recently, I have started to dislike the fact it produces .exe installer executables. This is a problem because:

  • An .exe-file immediately looks suspicious when downloading.
  • The binary installer code is from Inno Setup, and I have no control over it.
  • Lots of software (including the very dodgy type) use Inno Setup. This seems to confuse some antivirus applications, leading to false positives, quarantine, immediate destruction or bad av reputation for my Windows installers.
  • If the installer comes as .exe, admin rights have to be granted before it can be launched. Regular installers only require authorization once the installing happens, allowing to check the contents before giving privileges to the installer.

WiX Toolkit

Many times, I read the WiX Toolkit was a good way to create 'official' Windows .msi installers. I failed with previous attempts of using it, mostly because it's a complicated set of scripts on top of the already very complex Windows installer scripts and documentation is hard to come by and (at least to me) rather confusing. Additionally, it lacked some features I like to use - most importantly, to be able to gather all files in a directory to install as-is (for presets).

Version 5 has simplified things, but documentation is even harder to find. I spent a lot of time puzzling it all together from various sources and finally ended up with an .msi package that uses the regular Windows installation mechanism.

What is WiX?

WiX (Windows installer Xml) is a .xml based programmable preprocessor and a collection of scripts and libraries for various installer use-cases. It comes with WiXUI to create various installer dialogs flows. The xml used is not executed line-by-line (like the Inno Setup script), but things are defined as groups, properties and conditions that can be ordered and distributed over various files and 'fragments'. To complicate things further, UI and the actual installation routines are separated to enable distributed installations on networks, which wouldn't really be needed for this case. This means UI-data communication works using special properties only.

Unfortunately, my installers need to do some things that are non-trivial for Windows installers:

  • Write to subfolders of the Program Files directory and the user home directory during the same install.
  • Allow custom paths for vst2 plugins and user-data and store them to the registry for future updates/the installed plugin.
  • The apVerb installer needs to run the cpuid instruction to determine if the CPU supports AVX.
  • Allow downgrades to older versions.

Setup

  • Get Microsoft Visual Studio.
  • Add the HeatWave extension to Visual Studio. Created by Fire Giant, the makers of the WiX toolset, this installs the tools and enables building WiX-based installer packages using Visual Studio.
  • Restart Visual Studio to complete the installation.
  • The solution type I started out with is called "WiX Installer Package".
  • Download/Add the WixToolset.UI.wixext package using NuGet.

Source Code

In the hope to help others to create their plugin installers using WiX, I decided to upload my apVerb installer source code to GitHub. This is not a buildable project. The paths refer to my directory structure and the installed files are not included. It is supposed to serve as a point of reference and comparison when running into issues. I added an abundance of comments to the .wxs files to explain how I arrived at certain stuff.

https://github.com/Pflugshaupt/apVerb-WiX-Installer

Alternatively, here is a locally hosted .zip file with the source codes:

apVerb-WiX-Installer-src.zip

Starting with the template project, I renamed and added some files:

  • AvxDetectActionWiX.dll - A custom one-function .dll to check the AVX flag using cpuid. The source to build can be found in the AvxDetectActionWiX folder.
  • Banner493x312.bmp - An apulSoft branded .bmp file to be used on the initial and last installer dialog. The aspect ratio has to be exactly that, but I used double the resolution in order not to look blurry on HiDPI screens. With the low-color artwork I used, I found that Gimp does a great job at reducing the file size as much as possible.
  • Banner493x58.bmp - Same thing, but for middle dialogs. If these banners are not defined, you end up with a red CD icon... which looks rather weird in 2024.
  • EULA.rtf - The license text to be displayed before the installation starts.
  • Package.wxs - The main file with the main installer attributes: Properties are set up, groups of files are combined into selectable features, and extra steps of the installation are defined.
  • PluginStrings.en-us.wxl - A string table with dialog titles etc. This could be used to add localization, which was not done, and thus the feature descriptions are in Package.wxs.
  • PluginTargetFolders.wxs - describes the locations on disk things get installed to. I share this file between all the installers.
  • SourceFiles.wxs - This describes all groups of files that need to go into the package, where they get installed (using path properties) and what folders need removing on a full uninstall (only if they are empty).

ICE Validation

Some stuff my installers need to do does not pass the strict validation WiX/HeatWave does during builds. I had to disable some of the checks. These were about installing to a system folder and a user folder at the same time and about installing 32-bit dll files to 64-bit locations and vice versa (required by AAX / potentially VST3). This can be done in Visual Studio in the build settings.

Building from the Command Line.

To build the installer from the command line, the Visual Studio dotnet command can be used:

dotnet build .\apVerb-Installer.sln -v n -c Release /p:Platform=x64

Update: Building from the Command Line 2

It is also possible to call WiX directly from the command line without Visual Studio and HeatWave. This is faster than using dotnet, but debugging is much harder. To install wix.exe, use:

dotnet tool install --global wix

Here is my batch script:

set plugname=apVerb
set NUGET_PACKAGES=[YOUR USER FOLDER]\.nuget\packages
set WIXUI_DLL=%NUGET_PACKAGES%\wixtoolset.ui.wixext\5.0.1\wixext5\WixToolset.UI.wixext.dll

mkdir build
set outfile=build/%plugname%-installer.msi

wix build -v -o %outfile% -arch x64 -pdbtype full -ext %WIXUI_DLL% PluginStrings.en-us.wxl PluginTargetFolders.wxs Package.wxs SourceFiles.wxs

wix msi validate %outfile% -sice ICE38 -sice ICE64 -sice ICE91 -sice ICE80 -sice ICE57 -sice ICE61
 
Comments