Обновление службы Windows с помощью Inno Setup - PullRequest
14 голосов
/ 16 марта 2010

Я создал базовую установку службы Windows с помощью Inno Setup.как установка, так и удаление работают правильно.

Однако у меня возникли проблемы с процедурой обновления.

Для обновления исполняемого файла службы необходимо остановить службу, и только после полной остановки службы обновленное приложениеисполняемые файлы должны быть помещены в целевую папку.

Как выполнить команду остановки службы и дождаться полной остановки службы, прежде чем начнется этап развертывания файла?

Ответы [ 4 ]

18 голосов
/ 10 июля 2010

Код ниже взят со следующей страницы:
http://www.vincenzo.net/isxkb/index.php?title=Service_-_Functions_to_Start%2C_Stop%2C_Install%2C_Remove_a_Service

Однако мне пришлось применить небольшое исправление, чтобы оно заработало.

Обратите внимание, что я первоначально разместил этот ответ в 2010 году. Код на вышеприведенная страница была обновлена ​​в 2011 году, поэтому ее стоит посетить.

Я использую этот код в своем инсталляторе, как #include. Он скомпилирован в Inno Setup ANSI .
Он может работать для Unicode-версии Inno Setup, заменив A@ на W@ во всех объявлениях external (спасибо JeroenWiertPluimers за указание на это).

Также обратите внимание, что StartService и StopService просто отправляют сигнал запуска / остановки, но не ждут, пока служба перейдет в состояние останова. Вы можете создать код, который будет ожидать запуска службы, используя IsServiceRunning в сочетании с функцией Pascal Script Sleep(). Или просто Sleep() предварительно определенное количество секунд.

Код реализует следующие функции:

function IsServiceInstalled(ServiceName: string) : boolean;
function IsServiceRunning(ServiceName: string) : boolean;
function InstallService(FileName, ServiceName, DisplayName, Description : string;ServiceType,StartType :cardinal) : boolean;
function RemoveService(ServiceName: string) : boolean;
function StartService(ServiceName: string) : boolean;
function StopService(ServiceName: string) : boolean;
function SetupService(service, port, comment: string) : boolean;

Фактический код:

type
    SERVICE_STATUS = record
        dwServiceType               : cardinal;
        dwCurrentState              : cardinal;
        dwControlsAccepted          : cardinal;
        dwWin32ExitCode             : cardinal;
        dwServiceSpecificExitCode   : cardinal;
        dwCheckPoint                : cardinal;
        dwWaitHint                  : cardinal;
    end;
    HANDLE = cardinal;

const
    SERVICE_QUERY_CONFIG        = $1;
    SERVICE_CHANGE_CONFIG       = $2;
    SERVICE_QUERY_STATUS        = $4;
    SERVICE_START               = $10;
    SERVICE_STOP                = $20;
    SERVICE_ALL_ACCESS          = $f01ff;
    SC_MANAGER_ALL_ACCESS       = $f003f;
    SERVICE_WIN32_OWN_PROCESS   = $10;
    SERVICE_WIN32_SHARE_PROCESS = $20;
    SERVICE_WIN32               = $30;
    SERVICE_INTERACTIVE_PROCESS = $100;
    SERVICE_BOOT_START          = $0;
    SERVICE_SYSTEM_START        = $1;
    SERVICE_AUTO_START          = $2;
    SERVICE_DEMAND_START        = $3;
    SERVICE_DISABLED            = $4;
    SERVICE_DELETE              = $10000;
    SERVICE_CONTROL_STOP        = $1;
    SERVICE_CONTROL_PAUSE       = $2;
    SERVICE_CONTROL_CONTINUE    = $3;
    SERVICE_CONTROL_INTERROGATE = $4;
    SERVICE_STOPPED             = $1;
    SERVICE_START_PENDING       = $2;
    SERVICE_STOP_PENDING        = $3;
    SERVICE_RUNNING             = $4;
    SERVICE_CONTINUE_PENDING    = $5;
    SERVICE_PAUSE_PENDING       = $6;
    SERVICE_PAUSED              = $7;

{ nt based service utilities }
function OpenSCManager(lpMachineName, lpDatabaseName: string; dwDesiredAccess :cardinal): HANDLE;
external 'OpenSCManagerA@advapi32.dll stdcall';

function OpenService(hSCManager :HANDLE;lpServiceName: string; dwDesiredAccess :cardinal): HANDLE;
external 'OpenServiceA@advapi32.dll stdcall';

function CloseServiceHandle(hSCObject :HANDLE): boolean;
external 'CloseServiceHandle@advapi32.dll stdcall';

function CreateService(hSCManager :HANDLE;lpServiceName, lpDisplayName: string;dwDesiredAccess,dwServiceType,dwStartType,dwErrorControl: cardinal;lpBinaryPathName,lpLoadOrderGroup: String; lpdwTagId : cardinal;lpDependencies,lpServiceStartName,lpPassword :string): cardinal;
external 'CreateServiceA@advapi32.dll stdcall';

function DeleteService(hService :HANDLE): boolean;
external 'DeleteService@advapi32.dll stdcall';

function StartNTService(hService :HANDLE;dwNumServiceArgs : cardinal;lpServiceArgVectors : cardinal) : boolean;
external 'StartServiceA@advapi32.dll stdcall';

function ControlService(hService :HANDLE; dwControl :cardinal;var ServiceStatus :SERVICE_STATUS) : boolean;
external 'ControlService@advapi32.dll stdcall';

function QueryServiceStatus(hService :HANDLE;var ServiceStatus :SERVICE_STATUS) : boolean;
external 'QueryServiceStatus@advapi32.dll stdcall';

function QueryServiceStatusEx(hService :HANDLE;ServiceStatus :SERVICE_STATUS) : boolean;
external 'QueryServiceStatus@advapi32.dll stdcall';

function GetLastError() : cardinal;
external 'GetLastError@kernel32.dll stdcall';

function OpenServiceManager() : HANDLE;
begin
    if UsingWinNT() = true then begin
        Result := OpenSCManager('','',SC_MANAGER_ALL_ACCESS);
        if Result = 0 then
            MsgBox('the servicemanager is not available', mbError, MB_OK)
    end
    else begin
            MsgBox('only nt based systems support services', mbError, MB_OK)
            Result := 0;
    end
end;

function IsServiceInstalled(ServiceName: string) : boolean;
var
    hSCM    : HANDLE;
    hService: HANDLE;
begin
    hSCM := OpenServiceManager();
    Result := false;
    if hSCM <> 0 then begin
        hService := OpenService(hSCM,ServiceName,SERVICE_QUERY_CONFIG);
        if hService <> 0 then begin
            Result := true;
            CloseServiceHandle(hService)
        end;
        CloseServiceHandle(hSCM)
    end
end;

function InstallService(FileName, ServiceName, DisplayName, Description : string;ServiceType,StartType :cardinal) : boolean;
var
    hSCM    : HANDLE;
    hService: HANDLE;
begin
    hSCM := OpenServiceManager();
    Result := false;
    if hSCM <> 0 then begin
        hService := CreateService(hSCM,ServiceName,DisplayName,SERVICE_ALL_ACCESS,ServiceType,StartType,0,FileName,'',0,'','','');
        if hService <> 0 then begin
            Result := true;
            { Win2K & WinXP supports additional description text for services }
            if Description<> '' then
                RegWriteStringValue(HKLM,'System\CurrentControlSet\Services\' + ServiceName,'Description',Description);
            CloseServiceHandle(hService)
        end;
        CloseServiceHandle(hSCM)
    end
end;

function RemoveService(ServiceName: string) : boolean;
var
    hSCM    : HANDLE;
    hService: HANDLE;
begin
    hSCM := OpenServiceManager();
    Result := false;
    if hSCM <> 0 then begin
        hService := OpenService(hSCM,ServiceName,SERVICE_DELETE);
        if hService <> 0 then begin
            Result := DeleteService(hService);
            CloseServiceHandle(hService)
        end;
        CloseServiceHandle(hSCM)
    end
end;

function StartService(ServiceName: string) : boolean;
var
    hSCM    : HANDLE;
    hService: HANDLE;
begin
    hSCM := OpenServiceManager();
    Result := false;
    if hSCM <> 0 then begin
        hService := OpenService(hSCM,ServiceName,SERVICE_START);
        if hService <> 0 then begin
            Result := StartNTService(hService,0,0);
            CloseServiceHandle(hService)
        end;
        CloseServiceHandle(hSCM)
    end;
end;

function StopService(ServiceName: string) : boolean;
var
    hSCM    : HANDLE;
    hService: HANDLE;
    Status  : SERVICE_STATUS;
begin
    hSCM := OpenServiceManager();
    Result := false;
    if hSCM <> 0 then begin
        hService := OpenService(hSCM,ServiceName,SERVICE_STOP);
        if hService <> 0 then begin
            Result := ControlService(hService,SERVICE_CONTROL_STOP,Status);
            CloseServiceHandle(hService)
        end;
        CloseServiceHandle(hSCM)
    end;
end;

function IsServiceRunning(ServiceName: string) : boolean;
var
    hSCM    : HANDLE;
    hService: HANDLE;
    Status  : SERVICE_STATUS;
begin
    hSCM := OpenServiceManager();
    Result := false;
    if hSCM <> 0 then begin
        hService := OpenService(hSCM,ServiceName,SERVICE_QUERY_STATUS);
        if hService <> 0 then begin
            if QueryServiceStatus(hService,Status) then begin
                Result :=(Status.dwCurrentState = SERVICE_RUNNING)
            end;
            CloseServiceHandle(hService)
            end;
        CloseServiceHandle(hSCM)
    end
end;
7 голосов
/ 23 августа 2012

Начиная с Inno Setup 5.5.0, теперь доступны директивы CloseApplications и RestartApplications . Эти параметры будут определять используемые файлы и закрывать приложения, использующие их.

5 голосов
/ 17 марта 2010

Это две части:

  1. Как установщик, созданный с помощью Inno Setup, может запускать и останавливать службы, как он может создавать и удалять их, как он может изменить режим запуска?

    Используя вспомогательные функции, представленные в этом наборе подпрограмм , написанных именно для этой цели. Он написан для Ansi-версии Inno Setup, поэтому необходимо будет внести изменения в функции импорта API и типы параметров PChar, но это должно помочь вам начать работу.

  2. Как остановить существующую службу до копирования новой версии файла?

    У вас есть два основных способа сделать это. Вы должны использовать сценарии Pascal для выполнения функций, указанных выше, чтобы остановить службу, вам просто нужно решить, делать ли это в одной из функций события или делать это в пользовательской функции, которая будет вызываться через Check параметр записи файла для исполняемого файла службы. Я бы определенно сделал это в первом случае, чтобы вы могли проверить, была ли служба успешно остановлена, и запретить запуск установки в случае сбоя.

    Вам следует изучить функции событий CurStepChanged() и NextButtonClick(), в зависимости от того, нужно ли вам предотвратить следующий шаг. Примеры Inno Setup показывают использование обеих функций.

3 голосов
/ 12 января 2013

Я использую пакетный файл, который останавливает, удаляет, устанавливает и запускает данную службу, я просто вызываю пакетный файл, используя innosetup после того, как все файлы были скопированы.

[Run]
Filename: "{app}\Scripts\installwindowsService.bat"; Parameters: "{app}"; Flags: runhidden

Я поместил следующие команды в свой пакетный файл

net stop MyService

%SYSTEMROOT%\Microsoft.NET\Framework\v4.0.30319\installutil.exe /u MyService.exe 

%SYSTEMROOT%\Microsoft.NET\Framework\v4.0.30319\installutil.exe  MyService.exe /unattended

net start MyService

Это работает как шарм и очень просто. может использоваться для первой установки или для обновления. Надеюсь, это поможет вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...