How can I set recovery-options of a service with WiX?
Asked Answered
H

3

19

I have following .wxs-file:

<?xml version="1.0" encoding="UTF-8"?>
<?define ProductVersion="x.x.x.x" ?>
<?define UpgradeCode="{**MYGUID**}" ?>
<?define Manufacturer="My Company" ?>
<?define ProductName="My Product" ?>
<?define SkuName="MyProduct" ?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Product Id="*"
             Name="$(var.ProductName)"
             Language="1033"
             Version="$(var.ProductVersion)"
             Manufacturer="$(var.Manufacturer)"
             UpgradeCode="$(var.UpgradeCode)">
        <Package InstallerVersion="301"
                 Compressed="yes"
                 InstallPrivileges="elevated"
                 InstallScope="perMachine"
                 Platform="x86" />
        <Media Id="1"
               Cabinet="$(var.SkuName).cab"
               EmbedCab="yes" />
        <Directory Id="TARGETDIR"
                   Name="SourceDir">
            <Directory Id="ProgramFilesFolder">
                <Directory Id="ManufacturereDirectory"
                           Name="$(var.Manufacturer)">
                    <Directory Id="ProductDirectory"
                               Name="$(var.ProductName)" />
                </Directory>
            </Directory>
        </Directory>
        <ComponentGroup Id="MainComponentGroup">
            <Component Directory="ProductDirectory">
                <File Name="$(var.MyProject.TargetFileName)"
                      Source="$(var.MyProject.TargetPath)"
                      KeyPath="yes"
                      Vital="yes" />
                <ServiceInstall Id="SeviceInstall"
                                Name="$(var.ProductName)"
                                DisplayName="$(var.ProductName)"
                                Type="ownProcess"
                                Interactive="no"
                                Start="auto"
                                Vital="yes"
                                ErrorControl="normal"
                                Account="LOCALSYSTEM">
                </ServiceInstall>
                <ServiceControl Id="ServiceControl_Start"
                                Name="$(var.ProductName)"
                                Start="install"
                                Wait="no" />
                <ServiceControl Id="ServiceControl_Stop"
                                Name="$(var.ProductName)"
                                Stop="both"
                                Remove="uninstall"
                                Wait="yes" />
            </Component>
        </ComponentGroup>
        <Feature Id="MainFeature"
                 Level="1">
            <ComponentGroupRef Id="MainComponentGroup" />
        </Feature>
        <Upgrade Id="$(var.UpgradeCode)">
            <UpgradeVersion Property="UPGRADEFOUND"
                            Minimum="0.0.0.1" IncludeMinimum="yes"
                            Maximum="$(var.ProductVersion)" IncludeMaximum="yes"
                            OnlyDetect="no"
                            IgnoreRemoveFailure="yes"
                            MigrateFeatures="yes"/>
        </Upgrade>
        <CustomAction Id="ServiceRestarter"
                      Directory="ProductDirectory"
                      ExeCommand="&quot;[SystemFolder]sc.exe&quot; failure &quot;$(var.ProductName)&quot; reset= 60 actions= restart/0"
                      Impersonate="no" />
        <InstallExecuteSequence>
            <InstallExecute Before="RemoveExistingProducts" />
            <RemoveExistingProducts Before="InstallFinalize" />
            <Custom Action="ServiceRestarter" After="InstallFinalize"><![CDATA[NOT Installed]]></Custom>
        </InstallExecuteSequence>
    </Product>
</Wix>

Before that, I've tried:

<CustomAction Id="ServiceRestarter"
              Property="QtExecCmdLine"
              Value='"[SystemFolder]sc.exe" failure "$(var.ProductName)" reset= 60 actions= restart/0' />

which apparently called sc.exe - but changed nothing ...

Before that I've tried:

<ServiceInstall Id="SeviceInstall"
                Name="$(var.ProductName)"
                DisplayName="$(var.ProductName)"
                Type="ownProcess"
                Interactive="no"
                Start="auto"
                Vital="yes"
                ErrorControl="normal"
                Account="LOCALSYSTEM">
    <ServiceConfig Id="ServiceConfig"
                   DelayedAutoStart="yes"
                   OnInstall="yes"
                   OnReinstall="yes"
                   OnUninstall="no"
                   FailureActionsWhen="failedToStopOrReturnedError" />
    <ServiceConfigFailureActions Id="ServiceRestarter"
                                 OnInstall="yes"
                                 OnReinstall="yes"
                                 OnUninstall="no"
                                 ResetPeriod="0">
        <Failure Action="restartService" Delay="0" />
        <Failure Action="restartService" Delay="0" />
        <Failure Action="restartService" Delay="0" />
    </ServiceConfigFailureActions>
</ServiceInstall>

which did not work, as the MsiServiceConfigFailureActions table does not work if using an installer < 5.0, and even if using InstallerVersion="500" the only thing I get is an error:

Serivce 'My Product' (My Product) could not be configured. This could be a problem with the package or your permissions. Verify that you have sufficient privileges to configure system services.

(and yes, ... I've tried InstallPrivilges="elevated" also - but ... the real issue is Action="restartService" according to this)

So ... using a CustomAction is the way to go (or not?).

I have following output of the log

MSI (s) (34:28) [13:56:46:914]: Note: 1: 1722 2: ServiceRestarter 3: C:\Program Files (x86)\My Company\My Product\ 4: "C:\Windows\SysWOW64\sc.exe" failure "My Product" reset= 60 actions= restart/0
MSI (s) (34:28) [13:56:46:914]: Note: 1: 2205 2: 3: Error
MSI (s) (34:28) [13:56:46:914]: Note: 1: 2228 2: 3: Error 4: SELECT Message FROM Error WHERE Error = 1722
MSI (c) (2C:0C) [13:56:46:914]: Font created. Charset: Req=0, Ret=0, Font: Req=MS Shell Dlg, Ret=MS Shell Dlg

Error 1722. There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support personnel or package vendor. Action ServiceRestarter, location: C:\Program Files (x86)\My Company\My Product\, command: "C:\Windows\SysWOW64\sc.exe" failure "My Product" reset= 60 actions= restart/0
MSI (s) (34:28) [13:56:48:849]: Note: 1: 2205 2: 3: Error
MSI (s) (34:28) [13:56:48:849]: Note: 1: 2228 2: 3: Error 4: SELECT Message FROM Error WHERE Error = 1709
MSI (s) (34:28) [13:56:48:849]: Product: My Product -- Error 1722. There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support personnel or package vendor. Action ServiceRestarter, location: C:\Program Files (x86)\My Company\My Product\, command: "C:\Windows\SysWOW64\sc.exe" failure "My Product" reset= 60 actions= restart/0

Action ended 13:56:48: ServiceRestarter. Return value 3.
Action ended 13:56:48: INSTALL. Return value 3.

Can anybody help me out?

edit

I've used the old ServiceConfig-extension:

<util:ServiceConfig xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
                    FirstFailureActionType="restart"
                    SecondFailureActionType="restart"
                    ThirdFailureActionType="restart"
                    ResetPeriodInDays="1"
                    RestartServiceDelayInSeconds="20" />

which gives me a following build-error:

error CNDL0200: The ServiceInstall element contains an unhandled extension element 'util:ServiceConfig'. Please ensure that the extension for elements in the 'http://schemas.microsoft.com/wix/UtilExtension' namespace has been provided.

I know that I can resolve this error by using -ext WixUtilExtension via commandline - but I want to use Visual Studio for building ... So how can I adapt the build-command?

Only chance is to add a reference to WixUtilExtension.dll to my project.

Hare answered 18/9, 2012 at 11:59 Comment(2)
@david.barkhuizen actually, there is one available: stackoverflow.com/questions/tagged/wix4Hare
@david.barkhuizen my question specifically targets 3.5/3.6, so the introduction of the wix4 would be wrong - that's the reason why your edit got rejected (or otherwise I'd have reverted it)Hare
G
23

I can see that you've only tried the ServiceConfig element, which came with MSI 5.0. However, there's another ServiceConfig element in UtilExtension, which has been there for a long time and it seems that the thread you mention in your question confirms that it works.

The util:ServiceConfig element contains 3 parameters you'd like to use: FirstFailureActionType, SecondFailureActionType and ThirdFailureActionType, all accepting the same enumeration of values - none, reboot, restart and runCommand.

Try it out and if it works, it is far better choice than a custom action.

Glim answered 18/9, 2012 at 12:36 Comment(5)
I thought about that, but did not get it to work with 3.6. Can you provide me a working demo-code?Hare
Just add xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" to the root WiX elementGlim
Oh, you've guessed it out yourself - great! :)Glim
For those who use "visual studio", assure to reference WixUtilExtension.dllIbbetson
@Ibbetson like I've stated in the last sentence of my question ;)Hare
N
12

For WIX V 4.0, building with VS2015, the following works:

1: Ensure that WixUtilExtension.dll assembly is referenced by WIX project.

2: Add http://wixtoolset.org/schemas/v4/wxs/util ns to root Wix element. Note that this is the correct NS for WIX 4.0 (NOT http://schemas.microsoft.com/wix/UtilExtension as for previous versions).

<Wix
  xmlns="http://wixtoolset.org/schemas/v4/wxs"
  xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util"
  >

3: Ensure that ServiceConfig element is prefixed with correct namespace reference.

<ServiceInstall
      Id="MyService"
      Type="ownProcess"
      Name="MyService"
      DisplayName="MyService"
      Description="My Service"
      Start="auto"
      Account="[SERVICEACCOUNT]"
      Password="[SERVICEPASSWORD]"
      ErrorControl="normal"
    >

      <util:ServiceConfig
        FirstFailureActionType='restart'
        SecondFailureActionType='restart'
        ThirdFailureActionType='restart'            
        RestartServiceDelayInSeconds='30'
        ResetPeriodInDays='1'/>

</ServiceInstall>
Noah answered 21/1, 2016 at 13:44 Comment(3)
util:ServiceConfig also works with WIX version 3.10.0.1503, using the xmlns:util="schemas.microsoft.com/wix/UtilExtension" definition and the .dll referenceBrassard
The answer of @JaredDykstra not work to me. but thats give me an orientation. I found and try with this: <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"> and works. My version of WIX is 3.10.0.2103.Farias
Keep in mind "RestartServiceDelayInSeconds" is in seconds, but the Windows UI shows minutes, so if you set 30 seconds in this parameter, when viewed through the Windows UI, you'll see this parameter set to 0 minutes.Craigcraighead
F
1

In Visual Studio, to avoid using -ext in CLI you may do the following:

Of course, you add a resource: <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">

then, in Solution Explorer -> References -> Add.. WixUtilExtension.dll

After that everything works like a charm. (wix 3.10)

Of course, if you do use the second ServiceConfig from utils. Like <util:ServiceConfig blablabla

Foretell answered 6/2, 2017 at 17:15 Comment(1)
Thanks for your input, but that approach has already been suggested in other comments and answers :)Hare

© 2022 - 2024 — McMap. All rights reserved.