UI: Service: Restart clients on upgrade

This commit is contained in:
Nodir Temirkhodjaev 2024-05-02 10:47:15 +03:00
parent 67e90b03e5
commit f95ab81d98
11 changed files with 42 additions and 32 deletions

View File

@ -17,7 +17,8 @@
; Do not use the same AppId value in installers for other applications. ; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
SetupMutex=Global\{#APP_BASE}Setup SetupMutex=Global\{#APP_BASE}Setup
; Don't use AppMutex, and auto-restart the running instances ; Don't use AppMutex
RestartApplications=no
AppName={#APP_NAME} AppName={#APP_NAME}
AppVersion={#APP_VERSION_STR} AppVersion={#APP_VERSION_STR}
VersionInfoVersion={#APP_VERSION_STR} VersionInfoVersion={#APP_VERSION_STR}
@ -84,6 +85,7 @@ Name: "{commondesktop}\{#APP_NAME}"; Filename: "{#APP_EXE}"; WorkingDir: "{app}"
[Run] [Run]
; 1. Uninstall -> 2. Install Driver -> 3. Portable -> 4. Service ; 1. Uninstall -> 2. Install Driver -> 3. Portable -> 4. Service
Filename: "{#APP_EXE}"; Parameters: "-u most" Filename: "{#APP_EXE}"; Parameters: "-u most"
Filename: "{app}\driver\scripts\reinstall.bat"; Parameters: {code:DriverInstallArgs}; \ Filename: "{app}\driver\scripts\reinstall.bat"; Parameters: {code:DriverInstallArgs}; \
@ -311,12 +313,11 @@ begin
Result := True; Result := True;
end; end;
function StopFortService(var ResultCode: Integer): Boolean; function StopFortService(): Boolean;
var var
path: String; path: String;
ResultCode: Integer;
begin begin
ResultCode := -1;
path := ExpandConstant('{#APP_EXE}'); path := ExpandConstant('{#APP_EXE}');
if not FileExists(path) then if not FileExists(path) then
@ -325,7 +326,7 @@ begin
Exit; Exit;
end; end;
Exec(path, '-s', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) Exec(path, '-s', '', SW_HIDE, ewWaitUntilTerminated, ResultCode)
Result := (ResultCode = 0); Result := (ResultCode = 0);
end; end;
@ -446,15 +447,8 @@ begin
end; end;
function PrepareToInstall(var NeedsRestart: Boolean): String; function PrepareToInstall(var NeedsRestart: Boolean): String;
var
ResultCode: Integer;
begin begin
if Exec('sc.exe', ExpandConstant('stop {#APP_SVC_NAME}'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then StopFortService();
begin
if ResultCode <> 0 then StopFortService(ResultCode);
if ResultCode = 0 then Sleep(100); // Let the service to stop
end;
Result := ''; Result := '';
end; end;

View File

@ -1 +1 @@
@for %%f in (FortFirewall-*.exe) do @call .\%%f /SILENT /LAUNCH @for %%f in (FortFirewall-*.exe) do @call .\%%f /SILENT

View File

@ -428,6 +428,7 @@ HEADERS += \
util/osutil.h \ util/osutil.h \
util/processinfo.h \ util/processinfo.h \
util/regkey.h \ util/regkey.h \
util/service/service_types.h \
util/service/servicehandle.h \ util/service/servicehandle.h \
util/service/serviceinfo.h \ util/service/serviceinfo.h \
util/service/servicelistmonitor.h \ util/service/servicelistmonitor.h \

View File

@ -6,6 +6,7 @@
#include <QTimer> #include <QTimer>
#include <fortsettings.h> #include <fortsettings.h>
#include <manager/servicemanager.h>
#include <rpc/rpcmanager.h> #include <rpc/rpcmanager.h>
#include <task/taskinfoupdatechecker.h> #include <task/taskinfoupdatechecker.h>
#include <task/taskmanager.h> #include <task/taskmanager.h>
@ -80,11 +81,13 @@ void AutoUpdateManager::setupManager()
void AutoUpdateManager::setupRestart() void AutoUpdateManager::setupRestart()
{ {
if (IoC<FortSettings>()->isService()) if (IoC<FortSettings>()->isService()) {
return; connect(IoC<ServiceManager>(), &ServiceManager::stopRestartingRequested, this,
&AutoUpdateManager::restartClients);
if (!OsUtil::registerAppRestart()) { } else {
qCWarning(LC) << "Restart registration error"; if (!OsUtil::registerAppRestart()) {
qCWarning(LC) << "Restart registration error";
}
} }
} }

View File

@ -11,6 +11,7 @@
#include <control/controlmanager.h> #include <control/controlmanager.h>
#include <util/ioc/ioccontainer.h> #include <util/ioc/ioccontainer.h>
#include <util/osutil.h> #include <util/osutil.h>
#include <util/service/service_types.h>
#include <util/startuputil.h> #include <util/startuputil.h>
namespace { namespace {
@ -106,14 +107,14 @@ void ServiceManager::processControl(quint32 code, quint32 eventType)
state = SERVICE_RUNNING; state = SERVICE_RUNNING;
} break; } break;
case SERVICE_CONTROL_STOP: { case SERVICE_CONTROL_STOP: {
if (!acceptStop()) state = acceptStop() ? SERVICE_STOP_PENDING : 0;
break; } break;
case ServiceControlStopRestarting: {
emit stopRestartingRequested();
} }
Q_FALLTHROUGH(); Q_FALLTHROUGH();
case FORT_SERVICE_CONTROL_UNINSTALL: case ServiceControlStop:
case SERVICE_CONTROL_SHUTDOWN: { case SERVICE_CONTROL_SHUTDOWN: {
OsUtil::quit("service control"); // it's threadsafe
state = SERVICE_STOP_PENDING; state = SERVICE_STOP_PENDING;
} break; } break;
case SERVICE_CONTROL_DEVICEEVENT: { case SERVICE_CONTROL_DEVICEEVENT: {
@ -123,6 +124,10 @@ void ServiceManager::processControl(quint32 code, quint32 eventType)
} break; } break;
} }
if (state == SERVICE_STOP_PENDING) {
OsUtil::quit("service control"); // it's threadsafe
}
reportStatus(state); reportStatus(state);
} }

View File

@ -34,6 +34,7 @@ public:
signals: signals:
void pauseRequested(); void pauseRequested();
void continueRequested(); void continueRequested();
void stopRestartingRequested();
void driveListChanged(); void driveListChanged();
protected: protected:

View File

@ -0,0 +1,9 @@
#ifndef SERVICE_TYPES_H
#define SERVICE_TYPES_H
enum ServiceControlCode {
ServiceControlStop = 128,
ServiceControlStopRestarting,
};
#endif // SERVICE_TYPES_H

View File

@ -5,6 +5,7 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <qt_windows.h> #include <qt_windows.h>
#include "service_types.h"
#include "servicemanageriface.h" #include "servicemanageriface.h"
ServiceHandle::ServiceHandle( ServiceHandle::ServiceHandle(
@ -32,7 +33,7 @@ bool ServiceHandle::startService()
return StartServiceW(SC_HANDLE(m_serviceHandle), 0, nullptr); return StartServiceW(SC_HANDLE(m_serviceHandle), 0, nullptr);
} }
bool ServiceHandle::stopService() bool ServiceHandle::stopService(bool restarting)
{ {
int n = 3; /* count of attempts to stop the service */ int n = 3; /* count of attempts to stop the service */
do { do {
@ -41,9 +42,7 @@ bool ServiceHandle::stopService()
&& status.dwCurrentState == SERVICE_STOPPED) && status.dwCurrentState == SERVICE_STOPPED)
return true; return true;
const DWORD controlCode = (status.dwControlsAccepted & SERVICE_ACCEPT_STOP) != 0 const DWORD controlCode = restarting ? ServiceControlStopRestarting : ServiceControlStop;
? SERVICE_CONTROL_STOP
: FORT_SERVICE_CONTROL_UNINSTALL;
ControlService(SC_HANDLE(m_serviceHandle), controlCode, &status); ControlService(SC_HANDLE(m_serviceHandle), controlCode, &status);

View File

@ -26,7 +26,7 @@ public:
bool queryIsRunning(); bool queryIsRunning();
bool startService(); bool startService();
bool stopService(); bool stopService(bool restarting = false);
bool createService(const CreateServiceArg &csa); bool createService(const CreateServiceArg &csa);
bool deleteService(); bool deleteService();

View File

@ -3,8 +3,6 @@
#include <QObject> #include <QObject>
#define FORT_SERVICE_CONTROL_UNINSTALL 128
class ServiceManagerIface class ServiceManagerIface
{ {
public: public:

View File

@ -179,7 +179,7 @@ bool StartupUtil::stopService()
{ {
ServiceHandle svc(serviceNameStr, SC_MANAGER_ALL_ACCESS, SERVICE_ALL_ACCESS); ServiceHandle svc(serviceNameStr, SC_MANAGER_ALL_ACCESS, SERVICE_ALL_ACCESS);
if (svc.isServiceOpened()) { if (svc.isServiceOpened()) {
return svc.stopService(); return svc.stopService(/*restarting=*/true);
} }
return false; return false;