10

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):


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:

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

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Semonit
  • 379
  • 3
  • 14
  • Possible duplicate of [Wix stop service on uninstall/upgrade: prevent "restart popup" (file-in-use situation)](https://stackoverflow.com/questions/31787804/wix-stop-service-on-uninstall-upgrade-prevent-restart-popup-file-in-use-situ) – BartoszKP Jun 12 '17 at 19:33

2 Answers2

2

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.

PhilDW
  • 20,260
  • 1
  • 18
  • 28
  • In need to implement BOTH cases. For the first case, I know about the 30 seconds maximum waiting time. The service stopps within 30 seconds - but it seems, thats not happening/tried (eiter no log entry). My question was not about altering the sequencing of ServiceControl. For the second case, the service (another one) is not installed or prodived by this installer (but the files are!) - yes, that may be bad practice, but actually thats whats going on and I barely can change this. So, I need to schedule some custom-action before InstallValidate so that a file-in-use situation is prevented. – Semonit Jun 29 '15 at 13:51
  • You said that ServiceControl does not stop the service before InstallValidate, and I did not suggest moving ServiceControl. I tried to point that your statement is not relevant. If InstallValidate finds a service with in-use files and the service is in ServiceContrrol to be stopped then it will not do a files-in-use for the service. Of course if the service process has not gone away, or something else is going on then you will still get a files in use LATER. You should take a verbose log and check the in-use entries and what InstallValidate says about the service. – PhilDW Jun 29 '15 at 18:56
  • Sorry when I wasn't clear. If the process is creating child processes which are using file-resources, does the installer recognize these as well? The only message in the log that I would assign to my problem is: `RESTART MANAGER: Detected that application with id 120, friendly name 'javaw.exe', of type RmCritical and status 1 holds file[s] in use.` There is no entry saying that the service is being tried to stop at all. Shouldn't that be? – Semonit Jun 30 '15 at 12:30
  • The Restart Manager will find those files yes, and it looks like you have java involved in holding the files open. You should see something in ServiceControl if it's trying to stop the service, yes. But see my edit that may help. – PhilDW Jun 30 '15 at 17:51
  • thanks for your edit. but i get the same behaviour when using Stop="both". could it be a problem that the files that are used by the service (yes, the java process ;) ) are derived from another msi? – Semonit Jul 02 '15 at 07:51
  • No, that shouldn't matter. ServiceControl doesn't care what the service is, and it's still something in your scenario that needs to be stopped. It may be a java thing, I've heard that java processes often cause this type of issue. A full verbose log may help, in-use entries, process ids etc. – PhilDW Jul 02 '15 at 18:31
  • after a period of doing something different and now returned to this problem again. i could track down now, that on an uninstall, the restart manager is complaining about a running application "javaw.exe" as written previously. for me, it seems, that the restart manager does NOT recognize child processes of the service. i've got the following structure: service.exe->javaw.exe->xyz.exe->javaw.exe ("->" means parent of). is there a possibility, that the service is not returning the right status on start/stop even when it could be started/stopped without any problems by the services.msc? – Semonit Jul 30 '15 at 11:19
  • the ServiceControl table has the following entry: ServiceControl=MyService Name=MyService Event=161 Argument="" Wait=1 Component=MyService.exe the ServiceInstall table has: ServiceInstall=MyService Name=MyService DisplayName="My Service" ServiceType=16 StartType=2 ErrorControl=32769 LoadOrderGroup="" Dependencies="" StartName=".\LocalSystem" Password="" Arguments="--run" Component="MyService.exe" Description="My Service" – Semonit Jul 30 '15 at 11:26
  • a similar unanswered problem seems to be this: http://stackoverflow.com/questions/6913332/wix-installer-problem-why-does-restartmanager-mark-service-as-rmcritical-and-no – Semonit Jul 30 '15 at 13:25
1

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.

Arkady Sitnitsky
  • 1,846
  • 11
  • 22
  • could you please explain, how your solution is selecting the correct service? via "Name"? – Semonit Feb 19 '16 at 14:48
  • Yes by the name, this week i had the same issue and it solved it. – Arkady Sitnitsky Feb 19 '16 at 14:50
  • @ArkadySitnitsky Having just the same case 2 as OP, I'm starting service via CustomAction `sc start myservice`. Trying your approach but it takes no effect, still got a reboot warning after `InstallValidate` state. Is there any cases when it will not work? – Liastre Oct 30 '20 at 06:54