Blog

How to install Windows Service using Wix Harvesting and XLST
 

Today we will take a look at XSLT and heat. We have one (“relatively”) common scenario:

We harvest service project, and want to install that service. Now, this is possible with ServiceInstall/ServiceControl elements, however, once files are harvested, we have no access to them. It’s possible to manually change produced wxs file, but that is boring. In order to make it automatic, we can use XSL transformations, ¬†supported by heat. The idea of XSL transformations is that we can locate xml elements and transform them, from one state into another. The process is easy: find a SERVICE executable, and apply automatically ServiceInstall/ServiceControl flags.

Here is code that does it;

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                exclude-result-prefixes="msxsl"
                xmlns:wix="http://schemas.microsoft.com/wix/2006/wi"
                xmlns:my="my:my"
                xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">

  <xsl:output method="xml" indent="yes" />

  <xsl:strip-space elements="*" />
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="wix:Component[wix:File[@Source='$(var.EXCHANGE_Service.TargetDir)
                                       \EXCHANGE_Service.exe']]">

    <xsl:copy>
      <xsl:apply-templates select="node() | @*" />

      <wix:ServiceInstall Id="ExchangeServiceInstall"
						Name="yoursvc" 
						ErrorControl="ignore" 
						Start="auto"
						Type="ownProcess" 
						Vital="yes" 
						Interactive="no" 
						Account="[SERVICEUSER]"
						Password="[SERVICEPSWD]" />

      <wix:ServiceControl 
						Id="ExchangeServiceControl" 
						Name="yoursvc" 
						Start="install"
						Stop="both" 
						Remove="uninstall" 
						Wait="yes" />

    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

 

It’s possible to modify it for other usages, such as keeping generated GUIDS, versioning. EXCHANGE_Service is referenced by WiXProject. Now, if you want to apply that transform to heat, we can specify it with a flag:

heat dir "$(SolutionDir)EXCHANGE_Service\bin\$(Configuration)" 
		-sreg 
		-dr ServiceDir 
		-cg ServiceComponents 
		-gg -g1 -sf -srd 
		-var "var.EXCHANGE_Service.TargetDir" 
		-t "$(ProjectDir)ServiceHeatTransform.xslt" 
		-out "$(SolutionDir)WiXProject\ServiceHeat.wxs"

 

1 comment
  • Ivan Boyko

    Fantastic solution!
    Had to adjust namespaces a little, but it did work like a charm!
    Now off to learn XSLT properly! :))

Reply

Your email addres will not be published. All fields are required.