Separating a portion of WIX markup into its own library
As a project grows in complexity and size, we may end up with different teams building different parts of the software in relative isolation. Each team may want to control how their module will be installed or, during development, install only the modules that their code depends upon into their dev environment. To handle these scenarios, we can split our installer into chunks of WiX code called setup libraries.
A setup library can be compiled independently and plugged into the main, monolithic setup project later. We can also include the library in a team-owned setup project that only contains the modules required by the team. In essence, we can mix and match libraries wherever we need them to create installers for different purposes.
You might also want to share some complex installer markup, such as a user interface, with other installers, and a library is the perfect way to do this. Although it's outside the scope of this book, setup libraries are also used when building custom WiX extensions. In this recipe, we'll see how to create a setup library and include it in our setup project.
Getting ready
To prepare for this recipe, create a setup project and call it SetupLibraryInstaller
.
How to do it…
Add a setup library to the solution and reference it in a setup project. The following steps show how to do this:
- Add a new setup library to the same solution as the setup project by right-clicking on the solution in Solution Explorer and navigating to Add | New Project... | Windows Installer XML | Setup Library Project. For this example, name the project
MySetupLibrary
: - After it's created, right-click on the
MySetupLibrary
project in Solution Explorer and go to Add | New Item… | Text File. Name the text fileSampleTextFile.txt
and click on Add. Our library will install this single text file. - Right-click on the
MySetupLibrary
project in Solution Explorer again and select Properties. Select the Tool Settings tab and add-bf
, which stands for bind files, to the librarian textbox, as shown in the following screenshot: - Open
Library.wxs
and replace the existing markup with the following:<?xml version="1.0" encoding="UTF-8"?> <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> <Fragment> <DirectoryRef Id="INSTALLFOLDER"> <Directory Id="SampleComponentsDirectory" Name="Sample Components" /> </DirectoryRef> <ComponentGroup Id="SampleComponentGroup" Directory="SampleComponentsDirectory"> <Component Id="cmpSampleTextFileTXT" Guid="{5382BC02-4484-4C9B-8734-A99D20632EA9}"> <File Source="SampleTextFile.txt" /> </Component> </ComponentGroup> <Feature Id="SampleFeature"> <ComponentGroupRef Id="SampleComponentGroup" /> </Feature> </Fragment> </Wix>
- In the
SetupLibraryInstaller
project, add a reference to the setup library by right-clicking on the References node in Solution Explorer and selecting Add Reference…. Click on the Projects tab, highlightMySetupLibrary
, click on Add, and then on OK. - Open
Product.wxs
and add aFeatureRef
element with an ID ofSampleFeature
. This includes the feature we added to theLibrary.wxs
file ofSetupLibrary
in our installer.FeatureRef
can go after the existingFeature
element as follows:<Feature Id="ProductFeature" Title="ConsoleAppInstaller" Level="1"> <ComponentGroupRef Id="ProductComponents" /> </Feature> <FeatureRef Id="SampleFeature"/>
How it works…
Our setup library contains WiX markup to install a single text file called SampleTextFile.txt
. Ordinarily, when you build a library like this, the source files don't get stored within it. Instead, only the WiX markup is compiled without any of the source files it refers to. In that case, we would have had to copy SampleTextFile.txt
to the setup project's directory too, so that it can be found at link-time when compiling the installer.
However, because we added the -bf
flag, which stands for bind files, to the Librarian settings, the text file was serialized and stored within the library. The -bf
flag will handle serializing and storing any type of file including executables, images, and other binary data. Setup libraries are compiled into files with a .wixlib
extension.
The markup we added to the library created a component, directory, and feature for the text file. To integrate the new directory with the existing directory structure as defined by our setup project, we chose to reference INSTALLFOLDER
with a DirectoryRef
element. Just be sure that there's a corresponding Directory
element in your setup project that has this name. At link time, the DirectoryRef
element in the library is merged with the Directory
element in the setup project by matching their IDs. Once we had this, we were able to add a new subdirectory within the INSTALLFOLDER
directory called Sample Components. After installation, we can see that the new directory was created and it contains our text file:
To be sure that our library gets compiled before our setup project, we referenced it within the setup project using the References node. Then, to create a link to the library, we included a FeatureRef
element in Product.wxs
, which had an ID matching the Feature
defined in the library. This pulls the Feature
with all of its components into the installer.
There's more…
The setup libraries might contain more than just components, features, and directories. For example, they might define markup for a user interface using a UI
element, which could then be linked to our installer with a UIRef
element. Basically, if you can find a corresponding *Ref
element, such as DirectoryRef
, UIRef
, ComponentGroupRef
, or FeatureRef
, then you'll be able to separate that type of element into a library and use its *Ref
element to link it to the setup project.
Even if you can't find a corresponding *Ref
element, as long as you have a reference of some kind, such as Property
and PropertyRef
, the rest of the elements in the library will be carried along with it into the installer. So, at the very least, you could include a single Property
in the library and use that as the link between the library elements and the installer.