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)