Monday, January 17, 2011

Uninstalling Web Applications using WiX

I have recently been playing around with windows installers at work for our projects. I have never before had much success with this as I never put much effort into learning about creating installation files. So when a colleague turned up a Visual Studio project type called WiX i had a look.

Now using WiX is much the same as using MSBuild as it is all written in XML. I have never really liked XML based scripting as it is very verbose but WiX seems ok.

At work I we create installers for all of our web applications and have always had the problem of not being able to specify a custom name for the app in the installer as we were not able to uninstall it. So I reciently set about finding a solution.

After a few hours of googling I found this post on the WiX message board. The post was basically states that you store the custom name in a registry entry and call it back on uninstall. The example was a little bit unformatted for my liking but I managed to get the general idea of it.

After a bit of hacking I came up with this solution:


<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:iis="http://schemas.microsoft.com/wix/IIsExtension">
<Product Id="new guid here" Name="Product Name" >

<Property id="WEBAPPNAME">
<RegistrySearch id="WebAppName" root="HKLM" key="Software\[Manufacturer]\[ProductName]" name="WebAppName" type="raw"></RegistrySearch>
</Property>
<SetProperty id="WEBAPPNAME" value="WebAppName" after="AppSearch">WEBAPPNAME=""</SetProperty>

... Any extra properties and conditions here ...

<Media id="1" cabinet="media1.cab" embedcab="yes"></Media>
<Directory id="TARGETDIR" name="SourceDir">
<Directory id="ProgramFilesFolder">
<Directory id="INSTALLLOCATION" name="[ProductName]">
.... Add Files using components here ...

<Component id="WebAppNameComponent" guid="new guid here">
<RegistryValue id="WebAppName" root="HKLM" key="Software\[Manufacturer]\[ProductName]" name="WebAppName" type="string" value="[WEBAPPNAME]"></RegistryValue>
</Component>
<Component id="WebAppSetupIIS" guid="new guild here" keypath="yes">
<iis:WebVirtualDir id="WebApplicationDirectory" alias="[WEBAPPNAME]" Directory="[ProductName]" website="DefaultWebSite">
<iis:WebApplication id="WebApplication" name="[WEBAPPNAME]">
... IIS Settings here ...
</iis:WebApplication>
</iis:WebVirtualDir>
</Component>
</Directory>
</Directory>
</Directory>

<iis:WebSite id="DefaultWebSite" description="Default Web Site">
<iis:WebAddress id="AllUnassigned" port="80"></iis:WebAddress>
</iis:WebSite>

<Feature id="Complete">
<ComponentRef id="WebAppSetupIIS"></ComponentRef>
<ComponentRef id="WebAppNameComponent"></ComponentRef>
</Feature>

... Any UI stuff here ...
</Product>
</Wix>


So Basically I start a new WiX file and add a Product as you normally would in WiX.

I added a new Property called WEBAPPNAME (All in caps for some reason in WiX I have yet to research). And in this Property I do a RegistrySearch (search in the Windows Registry) for a key that is defaulted to the product name with a value for the WebAppName.

And since this has not been set in the initial installation of this product I perform a SetProperty and give it a default value. However this will overwrite any value that may exist so I put a condition on it that specifies that WEBAPPNAME has no value. And tell it to execute after an event called AppSearch which is when the registry is searched.

I then set up the directory structure of the install and add some Components to the directory.

The first Component is the WebAppNameComponent and this creates a value in the registry to the value of WEBAPPNAME. This registry value will also be removed on uninstall but exists solely to provide the name of the application at uninstall time.

The next Component is the WebAppSetupIIS component and this creates the entry in IIS providing the current directory as a virtual directory in IIS and sets the name of the virtual directory to the value of WEBAPPNAME.

Next I specified the WebSite that the web application would reside in and finally added the two components above into the feature by using the ComponentRef tags.

The rest of the file was just setting up the user interface and other things.

The final thing worth mentioning is that I added an entry in the UI to be able to change the name of the Virtual Directory in the installer.

All I needed to do was add these lines of code to the Dialog file in my project:


<Control Id="WebAppNameLabel" Type="Text" Text="Web Application Name:" />
<Control Id="WebAppNameEdit" Type="Edit" Text="[WEBAPPNAME]" Property="WEBAPPNAME" />

NOTE: Positioning and Size information removed for brevity from these tags

Well that is about it for uninstalling web applications with custom names.

Cheers.

1 comment:

  1. Erik, you might find my blog entry about the Remember Property pattern interesting: http://robmensching.com/blog/posts/2010/5/2/The-WiX-toolsets-Remember-Property-pattern There are a couple sneaky issues implementing it.

    ReplyDelete