Monday, October 27, 2008

Installing IIS7 UI Extensions With WiX

IIS7 includes a new set of APIs for building extensions for its UI configuration manager, inetmgr. Following the Understanding UI Extension Authoring guide on iis.net results in a pair of assemblies to be added to the GAC, a configuration schema, and some entries to be added to applicationHost.config and administration.config. This is basically a WiX-ification of the deployment guide available here.

All of these files are in %systemroot%\system32\inetsrv\config.

WiX XmlConfig

The XmlConfig element is what is used to edit existing XML files (XmlFile is used to edit files that are installed with your program). It's ugly and a pain to use correctly, but it does the trick. The reference that comes with WiX is decent, but it doesn't really show you how to use the thing.

The use of XmlConfig follows a basic pattern - create the element, add any attributes or sub-elements, and finally an XmlConfig to handle uninstallation.

applicationHost.config

The applicationHost.config file needs to be edited so that IIS7 can find the custom config section described by the schema file. This amounts to adding a <section name="wsgi" overrideMode="Deny" /> element to the configSections element.

<util:XmlConfig Id="appHostEntry"
                File="[IIS7LOCATION]\config\applicationHost.config"
                Action="create"
                ElementPath="//configuration/configSections/sectionGroup[\[]@name='system.webServer'[\]]"
                Name="section"
                Node="element"
                Sequence="1"
                On="install" />

<util:XmlConfig Id="appHostEntryName"
                File="[IIS7LOCATION]\config\applicationHost.config"
                ElementPath="appHostEntry"
                Name="name"
                Value="wsgi"
                Sequence="2" />

<util:XmlConfig Id="appHostEntryOverrideMode"
                File="[IIS7LOCATION]\config\applicationHost.config"
                ElementPath="appHostEntry"
                Name="overrideModeDefault"
                Value="Deny"
                Sequence="3" />

<util:XmlConfig Id ="removeAppHostEntry"
                File="[IIS7LOCATION]\config\applicationHost.config"
                Action="delete"
                ElementPath="//configuration/configSections/sectionGroup[\[]@name='system.webServer'[\]]"
                Node="element"
                VerifyPath="section[\[]@name='wsgi'[\]]"
                On="uninstall"
                Sequence="1" />

The first XmlConfig entry creates the section element under configSections. The next two add the attributes that I want. Note that the latter entries have their ElementPath pointing to the Id of the first entry. The final XmlConfig is used on uninstallation to remove the element.

administration.config

The entries in administration.config are used by inetmgr to find the admin modules. These follow the same basic pattern as the previous XmlConfig entries. These need to be added in two different spots, so the elements look similar for both cases.

Under moduleProviders:

<util:XmlConfig Id="adminModuleProvider" 
                File="[IIS7LOCATION]\config\administration.config" 
                Action="create" 
                ElementPath="//configuration/moduleProviders" 
                Name="add" 
                Node="element" 
                Sequence="1" 
                On="install" />

<util:XmlConfig Id="adminModuleProviderName" 
                File="[IIS7LOCATION]\config\administration.config" 
                ElementPath="adminModuleProvider" 
                Name="name" 
                Value="NWSGI" 
                Sequence="2" />

<util:XmlConfig Id="adminModuleProviderType" 
                File="[IIS7LOCATION]\config\administration.config" 
                ElementPath="adminModuleProvider" 
                Name="type" 
                Value="NWSGI.Management.NwsgiModuleProvider, NWSGI.Management, Version=0.6.0.0, Culture=neutral, PublicKeyToken=41e64ddc1bf1fc86" 
                Sequence="3" />

<util:XmlConfig Id ="removeAdminModuleProvider" 
                File="[IIS7LOCATION]\config\administration.config" 
                Action="delete" 
                ElementPath="//configuration/moduleProviders" 
                Node="element" 
                VerifyPath="add[\[]@name='NWSGI'[\]]" 
                On="uninstall" 
                Sequence="1" />

Under location:

<util:XmlConfig Id="adminModule"
                File="[IIS7LOCATION]\config\administration.config"
                Action="create"
                ElementPath="//configuration/location[\[]@path='.'[\]]/modules"
                Name="add"
                Node="element"
                Sequence="1"
                On="install" />

<util:XmlConfig Id="adminModuleName"
                File="[IIS7LOCATION]\config\administration.config"
                ElementPath="adminModule"
                Name="name"
                Value="NWSGI"
                Sequence="2" />

<util:XmlConfig Id ="removeAdminModule"
                File="[IIS7LOCATION]\config\administration.config"
                Action="delete"
                ElementPath="//configuration/location[\[]@path='.'[\]]/modules"
                Node="element"
                VerifyPath="add[\[]@name='NWSGI'[\]]"
                On="uninstall"
                Sequence="1" />

schema.xml

Installing the schema.xml file is done with a File element, just like any other file.