MSI: How a Service is stopped on uninstall during

2019-02-27 07:43发布

问题:

I want to know, how and when in concrete a service is tried to stop if it's marked as Remove="uninstall" Stop="uninstall" in the WiX Project File.

Why I'm asking: On uninstalling, the service is not recognized or handled correctly by the RESTART MANAGER resulting in the "restart dialog".

I attached the debugger to the service and realized, that it's never been tried to be stopped - at least, not via the registered ControlHandler. I was guessing, that it will be stopped in the same manner as executing "sc stop servicename" or by stopping it via the Services-Dialog. The service itself is written in C++ and the control handler is registerd by RegisterServiceCtrlHandler which works quite normally with the both outlined cases. The handler is invoked when stopping the service. Not so, if it's stopped/uninstalled via the MSI.

By the way, as stated by the answer of jbudreau in Wix Installer Problem: Why does RestartManager mark Service as RMCritical and not RMService can a service ever been stopped in the InstallValidate section if the service is running as LocalSystem? In InstallValidate, the uninstall-process is not elevated yet.

Some explanation of how the process of stopping a LocalSystem service is working on uninstall would be great!

Thanks in advance!

EDIT: Here is my service definition with ServiceInstall and ServiceControl:

        <DirectoryRef Id="BINDIR">
        <!-- the service -->
        <Component Id="myProgramsvc.exe" Guid="1f64c03f-26ea-47ba-985c-2a566afffffa">
            <File Id="myProgramsvc.exe" KeyPath="yes" Vital="yes"
                  Source="SourceDir\bin\myProgramsvc.exe"/>
            <ServiceInstall Id="MyProgramSvc" Type="ownProcess"
                            Vital="yes" Name="MyProgramSvc" DisplayName="Test MyProgram Service"
                            Description="Test MyProgram Service" Start="auto" Account=".\LocalSystem"
                            ErrorControl="normal" Interactive="no" Arguments="--run"/>
            <ServiceControl Id="MyProgramSvc" Name="MyProgramSvc" Wait="yes" Remove="uninstall" Stop="uninstall" Start="install"/>
        </Component>
    </DirectoryRef>

and the process hierarchy, where the RestartManager is complaining about the ----as.exe (PID: 4312): EDIT 2: (the id 9324 is different from the screenshot, took from the logfile of a differenty try)

MSI (s) (BC:38) [16:46:14:141]: RESTART MANAGER: Detected that application with id 9324, friendly name '---as.exe', of type RmCritical and status 1 holds file[s] in use.
MSI (s) (BC:38) [16:46:14:141]: RESTART MANAGER: Did detect that a critical application holds file[s] in use, so a reboot will be necessary.

EDIT 3: The Logfile: uninstall.log - the logfile is too large for posting here (30000 chars limitation).

回答1:

InstallValidate doesn't stop services - that's done by the StopServices action. InstallValidate is what tries to figure out what files are in use (with Restart Manager) and show a files-in-use dialog. Where services are concerned, it ignores any files in use by services that are in the ServiceControl table with a "stop at uninstall" setting. If you want to be sure that the service completely stops, use wait="yes". It's a standard stop service control handler call.

If the service fires off a bunch of processes that remain running then it's just an ordinary files-in-use issue and services are not relevant. Those processes need a shut-down call (from the service?) or they should integrate with Restart Manager, this kind of thing : http://www.codeproject.com/Articles/772868/Restart-Manager-Support-For-Windows-Application

If a process responds to windows messages the WiX util CloseApplication should shut it down.

I'll point out that you may simply have a bug in your WiX where the service named in your ServiceControl is incorrect. Since you can control any service (not just one you're installing/uninstalling) there is no check that the name corresponds to your service or any other. If you never see the service control stop being called this is the simplest explanation.