Creating setups for Visual Studio add-ins using Windows Installer XML (WiX)

Although as I have posted many times I personally use and recommend the free InnoSetup script-based tool to create the setup of my MZ-Tools family of add-ins (see HOWTO: Create a setup for a Visual Studio 2005 / 2008 add-in using Inno Setup), there are people who prefer MSI-based setups.

The tricky part of installing XML-based add-ins is always to decide where to put the .AddIn file (see INFO: Default .AddIn file locations for Visual Studio add-ins) and then to modify the <Assembly> value to point to the location where the user has decided to install the add-in dll (typically in the C:Program Files folder). This second part is always omitted from the Microsoft documentation and posts, because it requires a custom action, which is complicated because it requires code.

For this purpose, Windows Installer XML (Wix) greatly simplifies the task. WiX is a toolset that builds Windows installation packages from XML source code. Although I haven’t started to play with WiX yet, I have found that Alex Shevchuk has a great article series about moving from MSI to WiX, and specially interesting is the part 25 about updating XML files using XmlFile, which can be used to change the <Assembly> value.

I will try to find time to write a HOWTO article about this some day, but meantime, if you are interested, you can download the VS 2008 SDK 1.1 and go to the file C:\Program Files\Microsoft Visual Studio 2008 SDK\VisualStudioTeamSystemIntegration\Test Tool Extensibility\VsIdeHostAdapter\Installer\VsIdeTestHost.wxs, which uses this approach (bold line):

<!-- Directories -->
<DirectoryRef Id="TARGETDIR">
   <!-- One of the per-machine directories Visual Studio searchings for .Addin files -->
   <Directory Id="CommonAppDataFolder">
      <Directory Id="MSCommonAppData" Name="MS" LongName="Microsoft">
         <Directory Id="MSEnvCommonAppData" Name="MSEnvSH" LongName="MSEnvShared">
            <Directory Id="DIR_ADDINS" Name="Addins" />
   <!-- VS install dir replaced by RegistrySearch -->
   <Directory Id="VSINSTALLDIR" Name="VS2005" />

<!-- Components: files and registry entries -->
<DirectoryRef Id="DIR_ADDINS">
   <Component Id="C_VsIdeTestHostAddinXml" Guid="$(var.C_VsIdeTestHostAddinXml_Guid)">
      <File Id="VsIdeTestHostAddinFile" Name="HAAddin.ADD" Vital="yes" DiskId="1" LongName="$(var.AddinName).AddIn" Source="$(var.InstallerSources)\VsIdeTestHost.AddIn" />
      <XmlFile Id="AddAssemblyElement" Action="setValue" File="[#VsIdeTestHostAddinFile]" ElementPath="/Extensibility/Addin/Assembly" Value="[#VSIdeAddinDllFile]" Sequence="1" />
      <XmlFile Id="AddinNameElement" Action="setValue" File="[#VsIdeTestHostAddinFile]" ElementPath="/Extensibility/Addin/FriendlyName" Value="$(var.AddinName)" Sequence="1" />

BTW, notice that the sample uses the “CommonAppDataFolder” variable, which is localized on Windows, while Visual Studio has a bug hardcoding the English name (%ALLUSERSPROFILE%\Application Data\Microsoft\MSEnvShared\AddIns) so the sample doesn’t work on non-English machines, as explained in the article INFO: Default .AddIn file locations for Visual Studio add-ins.