Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inno Setup - properly stop service before file copy

Our installation process includes a Windows Service which is installed if our software is configured to be installed as a server (vs. a client installation). I added a service library to be able to manage the services, then in the files, I added handlers for BeforeInstall and AfterInstall events...

[Files]
Source: "MyService.exe"; DestDir: "{app}"; Check: IsServer; BeforeInstall: BeforeServiceInstall('MyServiceName', 'MyService.exe'); AfterInstall: AfterServiceInstall('MyServiceName', 'MyService.exe')

procedure BeforeServiceInstall(SvcName, FileName: String);
var
  S: Longword;
begin
  //If service is installed, it needs to be stopped
  if ServiceExists(SvcName) then begin
    S:= SimpleQueryService(SvcName);
    if S <> SERVICE_STOPPED then begin
      SimpleStopService(SvcName, True, True);
    end;
  end;
end;

procedure AfterServiceInstall(SvcName, FileName: String);
begin
  //If service is not installed, it needs to be installed now
  if not ServiceExists(SvcName) then begin
    if SimpleCreateService(SvcName, 'My Service Name', ExpandConstant('{app}')+'\' + FileName, SERVICE_AUTO_START, '', '', False, True) then begin
      //Service successfully installed
      SimpleStartService(SvcName, True, True);
    end else begin
      //Service failed to install

    end;
  end;
end;

When installing the service for the first time (doesn't already exist and isn't currently running), the installation/starting of this service works just fine. However, when running this installer on an existing installation (upgrade), the installer stops when it recognizes that this service is running, and prompts to terminate the process (before it calls the BeforeServiceInstall() handler)...

Prompt message

How do I prevent this prompt from appearing for services? I'm avoiding having to require a restart and would still like this prompt to appear for all other files.

like image 729
Jerry Dodge Avatar asked Jan 27 '14 20:01

Jerry Dodge


1 Answers

There is currently no direct way to exclude a file from checking if it's in use. You can disable this control globally (by setting CloseApplications directive value to no), which I wouldn't recommend. Or you can set a filter for files, which will be checked (in the CloseApplicationsFilter directive), which for you might require e.g. to list all the files except your service executable, which is hard to maintain.

You may also list all the files to be checked by specifying a filter which won't match any of your files and adding them from the RegisterExtraCloseApplicationsResources event method is the same as doing this from the mentioned directive.

What I would suggest is to stop your service from the PrepareToInstall event method. Its reference explicitly suggests this (emphasized by me):

You can use this event function to detect and install missing prerequisites and/or to shutdown any application which is about to be updated.

This event method is executed before all the file in use checks are performed and allows you to say that you need a system restart for cases when stopping of your service fails for some reason. If you wouldn't require restart, you may just return a string with some sensible message what happened to the user.

For your script it would just mean to move the code from your BeforeServiceInstall procedure to the PrepareToInstall event method and remove the BeforeInstall parameter from the entry.

like image 143
TLama Avatar answered Sep 20 '22 13:09

TLama