95 lines
3.0 KiB
Python
95 lines
3.0 KiB
Python
import os
|
||
import subprocess
|
||
import sys
|
||
import traceback
|
||
|
||
import servicemanager
|
||
import win32event
|
||
import win32service
|
||
import win32serviceutil
|
||
|
||
|
||
SERVICE_NAME = "InventeraServer"
|
||
SERVICE_DISPLAY_NAME = "Inventera Server"
|
||
|
||
|
||
def _application_directory():
|
||
executable = sys.executable if getattr(sys, "frozen", False) else __file__
|
||
return os.path.dirname(os.path.abspath(executable))
|
||
|
||
|
||
class InventeraWindowsService(win32serviceutil.ServiceFramework):
|
||
_svc_name_ = SERVICE_NAME
|
||
_svc_display_name_ = SERVICE_DISPLAY_NAME
|
||
_svc_description_ = (
|
||
"Автоматически запускает веб-сервер Inventera при старте Windows."
|
||
)
|
||
|
||
def __init__(self, args):
|
||
super().__init__(args)
|
||
self.stop_event = win32event.CreateEvent(None, 0, 0, None)
|
||
self.server_process = None
|
||
|
||
def SvcStop(self):
|
||
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
|
||
win32event.SetEvent(self.stop_event)
|
||
self._stop_server()
|
||
|
||
def SvcDoRun(self):
|
||
servicemanager.LogInfoMsg("Служба Inventera запускается.")
|
||
try:
|
||
self._run_server()
|
||
except Exception:
|
||
servicemanager.LogErrorMsg(
|
||
"Служба Inventera завершилась с ошибкой:\n"
|
||
+ traceback.format_exc()
|
||
)
|
||
raise
|
||
finally:
|
||
self._stop_server()
|
||
servicemanager.LogInfoMsg("Служба Inventera остановлена.")
|
||
|
||
def _run_server(self):
|
||
application_directory = _application_directory()
|
||
server_path = os.path.join(application_directory, "Inventera.Server.exe")
|
||
if not os.path.isfile(server_path):
|
||
raise FileNotFoundError(f"Не найден сервер Inventera: {server_path}")
|
||
|
||
creation_flags = getattr(subprocess, "CREATE_NO_WINDOW", 0)
|
||
self.server_process = subprocess.Popen(
|
||
[server_path],
|
||
cwd=application_directory,
|
||
creationflags=creation_flags,
|
||
)
|
||
|
||
while self.server_process.poll() is None:
|
||
wait_result = win32event.WaitForSingleObject(self.stop_event, 1000)
|
||
if wait_result == win32event.WAIT_OBJECT_0:
|
||
return
|
||
|
||
exit_code = self.server_process.returncode
|
||
self.server_process = None
|
||
raise RuntimeError(
|
||
"Inventera.Server.exe неожиданно завершился "
|
||
f"с кодом {exit_code}."
|
||
)
|
||
|
||
def _stop_server(self):
|
||
process = self.server_process
|
||
if process is None or process.poll() is not None:
|
||
self.server_process = None
|
||
return
|
||
|
||
process.terminate()
|
||
try:
|
||
process.wait(timeout=15)
|
||
except subprocess.TimeoutExpired:
|
||
process.kill()
|
||
process.wait(timeout=5)
|
||
finally:
|
||
self.server_process = None
|
||
|
||
|
||
if __name__ == "__main__":
|
||
win32serviceutil.HandleCommandLine(InventeraWindowsService)
|