How to restart dependent Windows service in case of a rollback?

31 Views Asked by At

I have a WiX 4 bundle that installs multiple MSIs (also authored using WiX 4), lets name them MsiA, MsiB and MsiC. All components are under my control. The updates in all MSIs are authored as MajorUpgrade with Schedule="afterInstallInitialize".

  1. MsiA installs a Windows service (MsiAService).
  2. MsiB also installs a Windows service (MsiBService) which depends on MsiAService.
  3. MsiC doesn't contain a service.

This order is also reflected in the Chain element of my bundle. All services are configured using ServiceInstall, ServiceDependency and ServiceControl elements.

Authoring of MsiA:

                   <ServiceInstall Id="S.MsiA.Service"
                                      Name="MsiAService"
                                      DisplayName="MSI A service"
                                      Description="MSI A service"
                                      Type="ownProcess"
                                      Start="auto"
                                      Account="LocalSystem"
                                      ErrorControl="normal"                                      
                                      Vital="yes">
                  </ServiceInstall>
                  <ServiceControl Id="S.MsiA.Service"
                                  Start="install"
                                  Stop="both"
                                  Remove="both"
                                  Name="MsiAService"
                                  Wait="yes" />
                  <util:ServiceConfig ServiceName="MsiAService"
                                      FirstFailureActionType="none"
                                      SecondFailureActionType="none"
                                      ThirdFailureActionType="none" />

Authoring of MsiB (which has the service dependency):

               <ServiceInstall Id="S.MsiB.Service" Name="MsiBService"
                                DisplayName="MSI B Service"
                                Description="MSI B Service"
                                Type="ownProcess" Start="auto" Account="LocalSystem"
                                ErrorControl="normal" Vital="yes">                    
                    <ServiceDependency Id="MsiAService"/>
                </ServiceInstall>               
                <ServiceControl Id="S.MsiB.Service"
                                Start="install"
                                Stop="both"
                                Remove="both"
                                Name="MsiBService"
                                Wait="yes" />               
                <util:ServiceConfig ServiceName="MsiBService"
                                    FirstFailureActionType="none"
                                    SecondFailureActionType="none"
                                    ThirdFailureActionType="none" />

Now, if I upgrade the bundle, and MsiB fails, the rollback takes place, which is desired.
But in this process, the following happens:

  1. MsiB is rolled back and starts it's MsiBService.
  2. The bundle of the previous version is started and re-installs MsiA: It stops it's MsiAService and since MsiBService dependends on it, it also gets shut down.
    After it's rollback, it starts its MsiAService.
  3. -> issue: the dependent service MsiBService stays stopped.

I looked up the service control elements in the WiX 4 documentation but couldn't find a solution to this problem.
Also in the Google results I couldn't find a solution.

I thought about using a CustomAction that restarts the service (via "net start") but I don't know how to formulate the condition for this use case and to which MSI I should add it.

Did anyone stumble across this problem and how did you solve this?
Or is there a built-in solution in WiX 4?

1

There are 1 best solutions below

1
Christopher Painter On

You can put a service control element in for a service you didn't install and if it's found MSI will handle that also. So if you author ServiceControl for service B in installer A it should give you what you are looking for.

Also, if service A is running elevated it could have code in it that spins up service B as needed. This would cover scenarios where B was down and it wasn't install time.