Big Chris
Big Chris

Reputation: 85

Wix Custom Actions to stop and start running windows services - issue where to call them?

Our installer currently "installs" a windows service exe i.e. it just copies the file on to the users PC, but doesn't start it.

Then when our app is run, it will "install" the service many times using InstallUtil and each instance of the service will have a different service name.

So when we come to upgrade our app, we have no idea how many of these services are running and what they are called - but we do know that their service name will start with "ABCService_".

So, I created a couple of VB.NET custom actions - one called "stopServices" and one called "startServices". The first one will scan the user's PC for any windows service that starts with "ABCService_" and store its name in an XML file in the temp folder along with an attribute stating whether the service was running or not. It will then stop each of the running services.

Then the normal installation would continue - the windows service exe will be upgraded etc

The second custom action, will do the opposite - it will read the xml file and start any service that was originally running.

Now in theory (in my mind) this should work - but the problem I have is where to place these custom actions within the wix msi code. I've currently got them as:

    <InstallExecuteSequence>
      <Custom Action="CA_StopWindowsServices"
              After="InstallInitialize" />

      <Custom Action="CA_StartWindowsServices"
              Before="InstallServices">
        <![CDATA[NOT Installed]]>  
      </Custom>
    </InstallExecuteSequence>

Because the custom actions alter the state of the PC, they have to be placed in the InstallExecuteSequence and Visual Studio tells me that the Stop action has to be after InstallInitialize and I thought having the start one before InstallServices might be a good place !?

BUT - this is my problem - when I run the msi; Windows complains that one of the files that needs to be upgraded (which is the windows service exe) is in use by how many instances of the service are running - which I knew would be a problem and hence why I wrote the custom actions; but I don't seem to be able to call the one that stops them before windows complains that they are in use ?!

Just thought that knowing how I defined the custom actions, might be relevent:

    <CustomAction
        Id="CA_StopWindowsServices"
        BinaryKey="CustomActionDLL"
        DllEntry="CustomActionStopServices"
        Execute="deferred"
        Return="check" />

    <CustomAction
        Id="CA_StartWindowsServices"
        BinaryKey="CustomActionDLL"
        DllEntry="CustomActionStartServices"
        Execute="commit"
        Return="check" />

Now saying all of that - I just ran my msi & when windows complained that 2 service instances were using files that needed to be replaced - I chose the first option, which is for windows to close them down and start them up at the end - which is basically what I'm trying to do :) So another question is - is it possible for me to tell windows to do this automatically - without it asking the user ? If it helps, the msi is actually run from a burn bootsrapper.

Many thanks in advance.

Cheers,

Big Chris.

Upvotes: 1

Views: 2052

Answers (1)

Brian Sutherland
Brian Sutherland

Reputation: 4798

Windows installer checks if files that will be replaced are in use during InstallValidate which happens before the InstallExecute sequence.

The problem is that you need elevation to stop the services which you don't have if you schedule a custom action before InstallValidate (usually).

In a bootstrapper, however, you can schedule tasks to stop the services before InstallValidate because the MSI always runs elevated from the elevated bootstrapper process that starts when you click install.

I haven't checked but adding a <ServiceControl> for the services in the MSI may automatically stop the services during the "StopServices" standard action and also avoid the FilesInUse dialog from InstallValidate. I haven't gotten around to testing this though since I already have a working solution with the bootstrapper.

So try your custom action solution but schedule your custom action to stop the services before InstallValidate.

Upvotes: 3

Related Questions