Wednesday, March 21, 2012

Creating a web service installer in Visual Studio 11 using WIX

So you have decided that you want to start using Visual Studio 11 and maybe you like me, did not pay that much attention when Microsoft said that visual studio setup projects vdproj will not ship with future versions of vs.
So what to do now with your setup projects that you have been used to, and relied on for your setup needs?
I am not saying that visual studio setup projects were a great technology, but they did the job, to some degree at least. You could very easily make an installer that did the job, particularly if your installation requirements were pretty simple, which I found they almost always were.
More often than not, the requirements basically was that the installer project should be built by the build server and versioned, stored in a repository and install the application to a web site or a folder depending on the type of project.

Well, what now, if you start Visual Studio 11 and select File->New Project you will quickly see that the only option left out of the box is InstallShield Limited Edition.

Personally I don't care too much for InstallShield and I have a feeling that starting using the Limited Edition would very soon prove to be too limited, even for simple stuff.
Wix is another option. It does not come out-of-the-box, but it is Open Source and can quickly be downloaded and installed.
I wish I also could say that you can quickly make an installer with it, but I am afraid I can't. When I set out to create my first Wix installer for a web service project I soon discovered that this was no easy task.
None of the Wix project templates that comes with the Wix installation will create an installer for a web service without heavy modification.
Wix is yet another example of a extremely poorly documented Open Source project. There's a lot of articles out there on the net, but I could not find any that were complete or without bugs, so I found myself spending a lot of time trying to figure out how to make this supposedly simple installer work.

In the hope of possibly saving others some of this pain I have made this write up which hopefully will be of some use to others.

To use wix with Visual Studio you currently need to download one of the weekly releases from, I started with v3.6.2712.0, but newer version will of course also be fine.

Installing it is as easy as clicking Install in their nice Metro style installer app

Then you are ready to start your Wix project. Select File->New Project and you should now see a new project category called Windows Installer XML with 4 project templates.
Select "Setup Project", enter Project Name and path to the folder were you want your project folder to be.

In your new project, locate the References node, and add a reference to the Web service project that you want to create an installer for.

Select the new reference and look at properties for this.
Change Project Output Groups to None as shown below:

Then we need to do a little manual editing of the project file.
To do this we need to first unload the project, right click the wix setup project and select "Unload Project".

Locate the Build configurations defined for your project, this would by default be Debug|x86 and Release/x86. Make sure that a constant named WebServiceProjectDir is added to all configurations. WebServiceProjectDir should define the path to the directory where your web service project is located.

When you are done it should look like this:

Then locate the ProjectReference you just added before starting the manual edit of the project file and add a WebProject tag as shown below.

Then add the following magic at the end of the file:
  <Target Name="BeforeBuild">
    <MSBuild Projects="%(ProjectReference.FullPath)" Targets="Package" Properties="Configuration=$(Configuration);Platform=AnyCPU" Condition="'%(ProjectReference.WebProject)'=='True'" />
    <HeatDirectory OutputFile="%(ProjectReference.Filename).wxs" Directory="%(ProjectReference.RootDir)%(ProjectReference.Directory)obj\$(Configuration)\Package\PackageTmp\" DirectoryRefId="INSTALLFOLDER" ComponentGroupName="%(ProjectReference.Filename)_Project" AutogenerateGuids="true" SuppressCom="true" SuppressFragments="true" SuppressRegistry="true" SuppressRootDirectory="true" ToolPath="$(WixToolPath)" PreprocessorVariable="var.WebServiceProjectDir" Condition="'%(ProjectReference.WebProject)'=='True'" />

And you are done with this file, yay!!!
Close the file and select "Reload Project"

Then we just need to add a number of Wix XML files to our Wix Setup Project. The XML files contains some weird arcane incantations that will make Wix produce an installer when the project is built.
  • English.wxl  : A kind of text resources file. Used to have all text strings in one place. You need to edit this to match your needs.
  • InstallationAddressDlg.wxs : Contains wix mumbo jumbo, you need to make two changes here
  • Conditions.wxi a file that contains a few checks that we want to run so see if we can install
  • MyUI.wxs : Contains wix mumbo jumbo, no need to change
  • Settings.wxi : Contains wix mumbo jumbo, no need to change
  • WebSites.wxi: Contains wix mumbo jumbo, no need to change

I have put all these files up on here: Wix files
You also want to replace the default Product.wxs with the one I have uploaded.
Then you need to do some modifications to English.wxl to match your setup.

The zip file contains an assembly called CustomActions.IIS.CA.dll in addition to the mentioned wix files. This assembly is needed to list the websites and virtual directories of your IIS server, which is required to know where to install the web service.
You can save this assembly anywhere on your disk, but you will need to modify InstallationAddressDlg.wxs so that it points to this assembly.

And that's it. You should now be able to build your setup project and it should produce a MSI file that will install your web service.
I will try to make a project template out of all this, and if I can make it work my next post will be about how to make a custom wix project template.

No comments:

Post a Comment