9
votes

Problem

I have an MSI that creates and starts a Windows service during installation and stops and removes the service during uninstallation. This works fine when installing and uninstalling by itself, but when upgrading, the Files in Use dialog is displayed (only on Vista and later due to the new Restart Manager), indicating that the service is in use.

Background

The Files in Use dialog is displayed during the InstallExecute sequence by the InstallValidate custom action, which is scheduled immediately before the RemoveExistingProducts custom action; this means that the previous version has not been uninstalled yet, so the Files in Use dialog should be shown.

The MSDN documentation indicates that the RemoveExistingProducts action must be scheduled after the InstallValidate action, and I currently have the RemoveExistingProducts actions scheduled immediately after the InstallValidate action.

Potential Solution

I would like to reschedule the RemoveExistingProducts custom action to immediately before the InstallValidate custom action so that the previous installation has a chance to stop and remove the service before the Files in Use dialog is shown. I tried rescheduling the actions, and it appears to work correctly with no adverse side-effects (although the log still indicates that the InstallValidate action executes before the RemoveExistingProducts action), but I'm hesitant to use this solution since it violates the MSDN documentation, and there may be adverse effects that I'm just not seeing yet.

Has anyone tried this? The only other alternative I can think of is to have the new installation stop the service of the old installation, but this is undesirable because it requires the installation to have information about all old installations that it can upgrade (stopping this particular service may involve more than just a simple call to the Service Manager to stop it).

4

4 Answers

6
votes

I implemented the potential solution outlined in the question, scheduling RemoveExistingProducts immediately before InstallValidate. I haven't seen any problems yet, but I will post again after the installation gets more use.

Update

Our installation has been using this for some time, and I haven't noticed any ill effects.

2
votes

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.

0
votes

One potential problem would be that if the user cancels during InstallValidate (e.g. due to not enough disk space or a file in use) or during the installation, what is the rollback behavior. The ideal situation is that the application state is the same as it was before (e.g. the previous application is installed). You might be giving that up with your sequencing, although rollback may be a feature you can live without.

0
votes

I think this one will help you without violating MSDN documentation and avoid any future issues. Put a condition "Installed OR PREVIOUSVERSIONSINSTALLED" and you will be good on upgrade too since the property PREVIOUSVERSIONSINSTALLED is set before InstallValidate action during FindRelatedProducts. I don't know why but the property PREVIOUSVERSIONSINSTALLED is not documented in MSDN but it does exist and very helpful, for me though.