Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WiX: stop service before RemoveExistingProducts OR run elevated CustomAction to stop process before RemoveExistingProducts

I ran into a problem on an major upgrade. The installer includes a service and on an upgrade I got a popup saying that a reboot is required to finish the setup process.

To prevent this behaviour I actually just need to stop the service before RemoveExistingProducts (rather InstallValidate) is executed.

The MajorUpgrade is placed after InstallInitialize and the package has InstallPrivileges="elevated".

I have two cases:


Case 1: The service is installed by ServiceInstall via

<Component Id="myservice_Service" Guid="*">
            <File Id="myservice.exe" KeyPath="yes" Vital="yes"
                  Source="SourceDir\bin\myservice.exe"/>
            <ServiceInstall Id="myservice_ServiceInstall" Type="ownProcess"
                            Vital="yes" Name="myservice" DisplayName="myservice Service"
                            Description="myservice Service" Start="auto" Account=".\LocalSystem"
                            ErrorControl="ignore" Interactive="no" Arguments="--run"/>
            <ServiceControl Id="myservice_ServiceControl" Name="myservice" Wait="yes" Stop="uninstall"/>
        </Component>

The ServiceControl is not stopping the service before InstallValidate is called. Even when saying Stop="both". So the popup appears. Note that the service is not started by the installer.

Reasonable posts I've found (excerpt):

  • How does one stop a Windows service to do an upgrade install?
  • Upgrade a Windows Service without Uninstalling

Case 2: The service is installed by a CustomAction (there are some reasons why not doing via ServiceInstall as well). In this case I have to call an executable to stop the service ("myservice.exe --stop"). For this it's getting tricky, since due to ICE63 it's not allowed to schedule a CustomAction before RemoveExistingProducts is called. So, how may I achieve this anyway?

So far I've read posts like:

  • WiX call app on uninstall before User prompt "close manually"
  • WiX close application before uninstall - close open applications message
  • Close a systemtray app before uninstalling using wix
  • http://t53456.windows-development-wix-user.wintalk.us/stop-a-service-before-uninstall-t53456.html

A bootstrapper exe is no option, since I need to produce an plain MSI.

I've found similar unanswered problem here: Wix Installer Problem: Why does RestartManager mark Service as RMCritical and not RMService

like image 320
Semonit Avatar asked Jun 25 '15 08:06

Semonit


2 Answers

The solution for case 2 is:

<DirectoryRef Id='INSTALLDIR'>
  <Component Id='StopService' Guid='{0913D365-8EC0-424A-939E-0F04E99D2ACA}' KeyPath='yes'>
    <ServiceControl Id='StopServiceControl' Name='ServiceName' Stop='uninstall' Wait='yes'/>
  </Component>
</DirectoryRef>

In that case no FileInUse dialaog will appear.

like image 178
Arkady Sitnitsky Avatar answered Sep 29 '22 11:09

Arkady Sitnitsky


The sequencing of ServiceControl after InstallValidate is irrelevant. If a file-in-use situation is detected for a service in InstallValidate but the service is in the ServiceControl table to be stopped at uninstall then Windows quite reasonably postpones any files-in-use situation to see what actually happens. If you take it out of ServiceControl you'll lose this potentially useful feature. Note that you can use ServiceControl independently of ServiceInstall - they are not bound together, so you don't necessarily need to run an exe to stop a service if it can play well with ServiceControl.

A common reason for this situation is simply that the service misbehaves. Wait=yes won't wait forever, only 30 seconds according to the documentation. So the service must respond to the control message telling it to stop. Even when the service is "stopped" that doesn't mean the process has gone away, only that it is no longer running as a service. If it takes a while to actually terminate the process then Windows has no alternative but to show files-in-use. These things are tricky to debug because timing issues typically are, but if it were me I'd be scrutinizing the service shutdown code.

Note also that you may need stop=both in an upgrade scenario. If InstallValidate (in your incoming upgrade) doesn't see an install stop in ServiceControl and there are files in use then you'll get that files-in-use issue. InstallValidate doesn't look ahead to see when RemoveExistingProducts might run and then go look in another MSI for a ServiceControl stop there that could prevent files-in-use.

like image 41
PhilDW Avatar answered Sep 29 '22 13:09

PhilDW