How does one stop a Windows service to do an upgra

2019-02-23 19:52发布

问题:

I have developed a Windows service along with a setup project using Visual Studio 2008. When I do an upgrade install I get the following warning:

The following applications are using files which the installer must update. You can either close the applications and click "Try Again", or click "Continue" so that the installer continues the installation, and replaces these files when your system restarts.

I would like to stop the Windows service during the upgrade install. I have tried creating a custom action and overriding the OnBeforeInstall methoc, however this gets called too late after the warning pop-up message has already occurred.

Is there any way to accomplish this as part of the msi installer. I would prefer to not have to do this as a separate task prior to executing the msi installer.

Update:
Based on further research I have found that the MSI database does support this, however the built-in Visual Studio installer (setup) projects do not provide a means to do this. One must either tweak the MSI database, or go with WiX or a commercial installer.

回答1:

Look at: Upgrade a Windows Service without Uninstalling



回答2:

If you want to go down the route of editing the MSI ServiceControl table, this following VBS script worked for me:

Dim installer, database, view, result
Set installer = CreateObject("WindowsInstaller.Installer")
Set database = installer.OpenDatabase ("Installer.msi", 1)
Set view = database.OpenView("INSERT INTO ServiceControl (ServiceControl,Name,Event,Arguments,Wait,Component_) VALUES ('ServiceName','ServiceName',170,null,null,'C__751A71A3822A287367770DB29839A759')") 
view.Execute
database.Commit
Set database = nothing


回答3:

Its already been built in to the MSI / Windows Installer ... the only problem is that the .NET installer classes doesn't use the MSI "Service Installation" features. What is actually happening is that the MSI is trying to install files and run a custom command using the files just copied (that is all Visual Studio is putting in the MSI).

To solve it you can edit the MSI with ORCA and add the following row to the ServiceControl table:

1   ServiceName 170     1   C__489628C5CC1144CB47F43E8BE7F3F31D

The Component ID you can lookup from the FILES table ... I just chose the main EXE file's Component ID. The 170 is a bitmap that tells the Windows Installer to stop and delete the service when Installing and Uninstalling.

This will clear the road for the .NET installers to add service and you can use the ServiceController to start the service after it's been installed via custom command.



回答4:

In WIX, I was able to get the service to shutdown before upgrade and uninstall by adding a "ServiceControl" element to stop the service on install. This seems to do the job, but everything related to MSI is close to black magic, so I am certainly open to any comments. Below is what my service component is defined as:

  <Component Id="ServicePrima" Guid="{d0847344-8632-4326-986c-78f4e02a41bb}">
    <ServiceControl Id="ServicePrima_BeforeInstall" Name="ServicePrima" Stop="install" Wait="yes"/>
    <File Name="PrimaPro.ServicePrima.Check.cmd" />
    <File Name="PrimaPro.ServicePrima.exe" Id="ServicePrimaExe" KeyPath="yes" />
    <File Name="PrimaPro.ServicePrima.exe.config" />
    <File Name="PrimaPro.ServicePrima.Install.cmd" />
    <File Name="PrimaPro.ServicePrima.pdb" />
    <File Name="PrimaPro.ServicePrima.Restart.cmd" />
    <File Name="PrimaPro.ServicePrima.SignalRestart.cmd" />
    <File Name="PrimaPro.ServicePrima.Uninstall.cmd" />
    <File Name="PrimaPro.ServicePrima.xml" />
    <ServiceInstall Id="ServicePrima_Install" Name="ServicePrima" DisplayName="PrimaPro - ServicePrima"
                    Type="ownProcess" Start="auto" Interactive="no" ErrorControl="normal"
                    Description="Manages the database synchronization and configuration management of the PrimaPro System and databases on a machine.">
    </ServiceInstall>
    <!-- Do not need to start service here (i.e. attribute Start="install"), the service will be started by "RestartServices" custom action. -->
    <ServiceControl Id="ServicePrima_AfterInstall" Name="ServicePrima" Stop="uninstall" Remove="uninstall" Wait="yes"/>
  </Component>