A pattern I like to use is creating an extension point in my WiX installer, called Extension.wxs
. The default (or standard) version of this file looked like the following:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="INSTALLLOCATION">
<!-- Setup all of the extension components here. -->
<!-- For example...
<Component Id="INSERT_COMPONENT_ID_HERE" Guid="{8451AFA1-5185-468D-B0A0-650494251D8F}">
<File Id="INSERT_FILE_ID_HERE" KeyPath="yes" Source="SomeExtension.dll" />
</Component> -->
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup Id="ExtensionComponentGroup">
<!-- Reference components that are extending the standard product here -->
<!-- <ComponentRef Id="INSERT_COMPONENT_ID_HERE" /> -->
</ComponentGroup>
</Fragment>
</Wix>
Wherever your Feature
is defined that you want to customize, you would add a reference to this ExtensionComponentGroup
, like so:
<Feature Id="MyMainFeature"
Title="My Main Feature"
Level="1"
Description="An awesome feature, needed to run the application.">
<ComponentGroupRef Id="MyMainComponentGroup" />
<ComponentGroupRef Id="ExtensionComponentGroup" />
</Feature>
In my case, I just use a set of Powershell scripts to build out my installer, because it makes it easier to dynamically determine what to feed into the WiX Toolset CLI. So, my standard invocation of candle.exe
would look like the following:
"C:\Program Files (x86)\WiX Toolset v3.11\bin\candle.exe" -out .\obj .\src\Product.wxs .\src\Extension.wxs
However, when I need to customize the installer with client specific files, I simply change the command line such that it points to the customized Extension.wxs
file (sort of 'injecting' it into the build pipeline):
"C:\Program Files (x86)\WiX Toolset v3.11\bin\candle.exe" -out .\obj .\src\Product.wxs .\SomeClientWithSpecialNeeds\Extension.wxs
Customizing these command line invocations becomes much easier when using Powershell, but I've omitted the Powershell scripts for the sake of simplicity.
In summary, I'm suggesting that you represent the contents of your zip file as individual Component
elements in a separate Extension.wxs
file that you inject into your installer's build pipeline. These components are stored in a ComponentGroup
that is referenced by the appropriate Feature
. By creating a suitable default (empty, devoid of components) Extension.wxs
file you can still perform a build without any custom components. The other benefit of using this pattern, is that all of the extra components will be uninstalled during uninstallation of the product, and you won't have to write any flaky custom actions that add to maintenance overhead for your installer!
Hope this helps someone.