I'm using HeatDirectory to create source .wxs file. In the pickup directory there is an exe which should be installed as service. Actually I know how to install service if I create component myself, but I don't know how to include ServiceInstall in auto generated component. Is there any suggestion?
<HeatDirectory DirectoryRefId="Guardian" OutputFile="Source\GuardianSource.wxs" Transforms="Filter.xsl" Directory="..\Setup\C24.Guardian\bin\Debug" PreprocessorVariable="var.GuardianPath" ComponentGroupName="GuardianGroup" ToolPath="$(WixToolPath)" SuppressCom="true" SuppressFragments="true" SuppressRegistry="true" SuppressRootDirectory="true" AutoGenerateGuids="true" GenerateGuidsNow="false">
</HeatDirectory>
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="Guardian">
<Component Id="cmp70BEDA00F3161F3FB5E847EB1136B1D5" Guid="*">
<File Id="fil26DCBF1E4218C7363018FBA2CD456633" KeyPath="yes" Source="$(var.GuardianPath)\C24.Guardian.exe" />
</Component>
<Component Id="cmp2EE8126A193FA022ED35FAD8F182E65A" Guid="*">
<File Id="fil785CD681C496EDDAB457E8314C49D686" KeyPath="yes" Source="$(var.GuardianPath)\C24.Guardian.exe.config" />
</Component>
<Component Id="cmp0CC91B457FBC44F978A2AD6B24043DCF" Guid="*">
<File Id="fil2D304D0395599AAAAAF975A2DBFD530F" KeyPath="yes" Source="$(var.GuardianPath)\C24.Guardian.pdb" />
</Component>
<Component Id="cmpFB799FA015274DDBE2C337C60667D2C5" Guid="*">
<File Id="filB9C39B394CAD03F5A1BC3262C61EDDEB" KeyPath="yes" Source="$(var.GuardianPath)\C24.Guardian.vshost.exe" />
</Component>
<Component Id="cmp28C29865AE85B067BCEEBD70EFDB19D5" Guid="*">
<File Id="fil0A756B711769AAD657F306B3A6EA7134" KeyPath="yes" Source="$(var.GuardianPath)\C24.Guardian.vshost.exe.config" />
</Component>
<Component Id="cmp92A715A4BD4B580A6E70362230170428" Guid="*">
<File Id="filBD9D504F303A6EEC9E340E3872BBB0AE" KeyPath="yes" Source="$(var.GuardianPath)\C24.Guardian.vshost.exe.manifest" />
</Component>
<Component Id="cmp8AB6A241FA2D13F296CBD946C9711579" Guid="*">
<File Id="fil8EF8CC607CB82B32F84FC9EC2F1636B9" KeyPath="yes" Source="$(var.GuardianPath)\com.Contact24.Tools.dll" />
</Component>
<Component Id="cmpC0DBB85C89E8AEA9BAC6E32B85913A2C" Guid="*">
<File Id="fil917CD649C5C318C6717D8EA9FFDF911A" KeyPath="yes" Source="$(var.GuardianPath)\com.Contact24.Tools.pdb" />
</Component>
<Component Id="cmp8AFB0FC7CCF571B61196D9166DEEBA24" Guid="*">
<File Id="fil32C12DF0163D5BAD7D0495F2CA2C8DA1" KeyPath="yes" Source="$(var.GuardianPath)\ICSharpCode.SharpZipLib.dll" />
</Component>
<Component Id="cmpF5DE5EB2B4C6E33F0C32CFF5F464432C" Guid="*">
<File Id="fil3C8C6F29095A04034E72FBB187F8B841" KeyPath="yes" Source="$(var.GuardianPath)\log4net.dll" />
</Component>
<Component Id="cmp27A7791E229DDDBC065069B26138FC2F" Guid="*">
<File Id="fil8DED592D9F63E708FEF848D2980A5186" KeyPath="yes" Source="$(var.GuardianPath)\log4net.xml" />
</Component>
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup Id="GuardianGroup">
<ComponentRef Id="cmp70BEDA00F3161F3FB5E847EB1136B1D5" />
<ComponentRef Id="cmp2EE8126A193FA022ED35FAD8F182E65A" />
<ComponentRef Id="cmp0CC91B457FBC44F978A2AD6B24043DCF" />
<ComponentRef Id="cmpFB799FA015274DDBE2C337C60667D2C5" />
<ComponentRef Id="cmp28C29865AE85B067BCEEBD70EFDB19D5" />
<ComponentRef Id="cmp92A715A4BD4B580A6E70362230170428" />
<ComponentRef Id="cmp8AB6A241FA2D13F296CBD946C9711579" />
<ComponentRef Id="cmpC0DBB85C89E8AEA9BAC6E32B85913A2C" />
<ComponentRef Id="cmp8AFB0FC7CCF571B61196D9166DEEBA24" />
<ComponentRef Id="cmpF5DE5EB2B4C6E33F0C32CFF5F464432C" />
<ComponentRef Id="cmp27A7791E229DDDBC065069B26138FC2F" />
</ComponentGroup>
</Fragment>
</Wix>
It'll be good to get something like the following code auto generated:
<ComponentRef Id="cmp70BEDA00F3161F3FB5E847EB1136B1D5">
<ServiceInstall
Id="ServiceAdminGuardianInstaller"
Type="ownProcess"
Vital="yes"
Name="C24.Guardian"
DisplayName="C24.Guardian"
Description="Служба контроля работы сервера администрирования"
Start="auto"
Account="[SERVICEACCOUNT]"
Password="[SERVICEPASSWORD]"
ErrorControl="ignore"
Interactive="no">
<util:PermissionEx
User="Everyone"
GenericAll="yes"
ServiceChangeConfig="yes"
ServiceEnumerateDependents="yes"
ChangePermission="yes"
ServiceInterrogate="yes"
ServicePauseContinue="yes"
ServiceQueryConfig="yes"
ServiceQueryStatus="yes"
ServiceStart="yes"
ServiceStop="yes"/>
</ServiceInstall>
<ServiceControl Id="StopGuardianService" Name="C24.Guardian" Stop="both" Wait="yes" Remove="uninstall" />
</ComponentRef>
As an alternative to the method described by @sttaq, what I usually do is filter out the .exe files and manage them manually. You're already filtering your heat output with an xsl file (Filter.xsl), so it should be easy to add a rule to filter out any *.exe file.
<!--Match and ignore .exe files-->
<xsl:key name="exe-search" match="wix:Component[contains(wix:File/@Source, '.exe')]" use="@Id"/>
<xsl:template match="wix:Component[key('exe-search', @Id)]"/>
<xsl:template match="wix:ComponentRef[key('exe-search', @Id)]"/>
And then, in your .wxs file, you can manually author the .exe file component including your service installer, icons, or anything you may need. Just remember to put it inside the right Directory:
<Fragment>
<DirectoryRef Id="dirA9BC717C5B7BCAAF2B4C1161965AD894">
<Component Id="ExecFileComponent" Guid="YOUR-GUID-HERE">
<RemoveFile Id="RemoveLogFiles" Name="*.svclog" On="both"/>
<File Id="ExecFile" Source="$(exefile)" KeyPath="yes" />
<ServiceInstall Id="ServiceInstallation" DisplayName="displayname" Name="name" ErrorControl="normal" Start="auto" Type="ownProcess" Vital="yes">
<util:PermissionEx
User="Everyone"
GenericAll="yes"
ServiceChangeConfig="yes"
ServiceEnumerateDependents="yes"
ChangePermission="yes"
ServiceInterrogate="yes"
ServicePauseContinue="yes"
ServiceQueryConfig="yes"
ServiceQueryStatus="yes"
ServiceStart="yes"
ServiceStop="yes" />
</ServiceInstall>
<ServiceControl Id="ServiceControl" Name="name" Stop="both" Remove="uninstall" />
</Component>
</DirectoryRef>
</Fragment>
I assume that you already know the name of your file that needs to be wrapped in a ServiceInstall
element.
This can be achieved using xsl transformation. The process can be automated using the XslTransformation
MSBuild task. Here is what I have done recently:
In the wixproj
file in the BeforeBuild
target add some parameters to pass on to the xsl, if you like you can hard code these in your xsl and skip this step:
<PropertyGroup>
<WixServiceParams>
<Parameter Name="InstallFolder" Value="INSTALLFOLDER" />
<!-- INSTALLFOLDER is Guardian in your case -->
<Parameter Name="DisplayName" Value="Service Display Name" />
<Parameter Name="Name" Value="ServiceName" />
<Parameter Name="Description" Value="Service Description." />
</WixServiceParams>
<DefineConstants>...</DefineConstants>
</PropertyGroup>
Then after your HeatDirectory task call the XslTransformation task like this:
<XslTransformation XslInputPath="WixService.xsl" XmlInputPaths="Input.wxs" OutputPaths="Final.wxs" Parameters="$(WixServiceParams)" />
Add the WixService.xsl
transformation file to your project. The file is as below:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wix="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:param name="InstallFolder"/>
<xsl:param name="DisplayName"/>
<xsl:param name="Name"/>
<xsl:param name="Description"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- Set Directory Reference to INSTALLFOLDER (set if required) -->
<xsl:template match="wix:DirectoryRef/@Id">
<xsl:attribute name="Id">
<xsl:value-of select="$InstallFolder"/>
</xsl:attribute>
</xsl:template>
<!-- XSL Template to inject WiX service installation elements to a .wxs generated from Heat Project task -->
<!-- There may be other ways to look for your file -->
<xsl:template match='wix:Wix/wix:Fragment/wix:DirectoryRef/wix:Component[wix:File[@Source="PATH-TO\YourService.exe"]]'>
<xsl:element name="wix:Component">
<xsl:attribute name="Id">
<xsl:value-of select="@Id"/>
</xsl:attribute>
<xsl:attribute name="Guid">
<xsl:value-of select="@Guid"/>
</xsl:attribute>
<xsl:element name="wix:File">
<xsl:attribute name="Id">
<xsl:value-of select="wix:File/@Id"/>
</xsl:attribute>
<xsl:attribute name="Source">
<xsl:value-of select="wix:File/@Source"/>
</xsl:attribute>
<xsl:attribute name="KeyPath">yes</xsl:attribute>
</xsl:element>
<xsl:element name="wix:ServiceInstall">
<!-- Service Install -->
<xsl:attribute name="Id">SERVICEINSTALLER</xsl:attribute>
<xsl:attribute name="DisplayName">
<xsl:value-of select="$DisplayName"/>
</xsl:attribute>
<xsl:attribute name="Name">
<xsl:value-of select="$Name"/>
</xsl:attribute>
<xsl:attribute name="Description">
<xsl:value-of select="$Description"/>
</xsl:attribute>
<xsl:attribute name="Start">auto</xsl:attribute>
<xsl:attribute name="Type">ownProcess</xsl:attribute>
<xsl:attribute name="Account">[USERNAME]</xsl:attribute>
<xsl:attribute name="Password">[PASSWORD]</xsl:attribute>
<xsl:attribute name="ErrorControl">normal</xsl:attribute>
<xsl:attribute name="Vital">yes</xsl:attribute>
<!-- Service Dependencies, if required -->
<xsl:element name="wix:ServiceDependency">
<xsl:attribute name="Id">DEPENDENCY</xsl:attribute>
</xsl:element>
<!-- Service Configuration, set as required -->
<xsl:element name="util:ServiceConfig">
<xsl:attribute name="FirstFailureActionType">restart</xsl:attribute>
<xsl:attribute name="SecondFailureActionType">restart</xsl:attribute>
<xsl:attribute name="ThirdFailureActionType">none</xsl:attribute>
<xsl:attribute name="RestartServiceDelayInSeconds">60</xsl:attribute>
</xsl:element>
</xsl:element>
<!-- Service Control, set as required -->
<xsl:element name="wix:ServiceControl">
<xsl:attribute name="Id">SERVICECONTROLLER</xsl:attribute>
<xsl:attribute name="Name">
<xsl:value-of select="$Name"/>
</xsl:attribute>
<xsl:attribute name="Remove">uninstall</xsl:attribute>
<xsl:attribute name="Stop">uninstall</xsl:attribute>
<xsl:attribute name="Wait">no</xsl:attribute>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
once done wish for a better way of doing this...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With