wix HeatDirectory ServiceInstall

2020-02-10 03:46发布

问题:

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>

回答1:

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>


回答2:

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...



标签: wix heat