This commit is contained in:
2025-09-26 21:56:06 +03:00
parent c17812a0c1
commit 2216f21c47
17 changed files with 3361 additions and 631 deletions

View File

@@ -0,0 +1,175 @@
#!/usr/bin/env python3
"""
Windows Service Wrapper - Handles Windows Service Communication
Fixes Error 1053 by properly communicating with Service Control Manager
"""
import sys
import os
import time
import logging
import subprocess
import threading
import signal
from pathlib import Path
# Simple service state management
class WindowsServiceManager:
def __init__(self):
self.service_process = None
self.should_stop = False
self.service_thread = None
def setup_logging(self):
"""Setup service logging."""
log_dir = os.path.join(os.path.expanduser("~"), "PrintService", "logs")
os.makedirs(log_dir, exist_ok=True)
log_file = os.path.join(log_dir, f"service_wrapper_{time.strftime('%Y%m%d')}.log")
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(log_file, encoding='utf-8'),
logging.StreamHandler(sys.stdout)
]
)
def signal_handler(self, signum, frame):
"""Handle shutdown signals."""
logging.info(f"Service wrapper received signal {signum}")
self.stop_service()
def start_service(self):
"""Start the actual print service."""
script_dir = Path(__file__).parent
service_script = script_dir / "print_service_complete.py"
if not service_script.exists():
logging.error(f"Service script not found: {service_script}")
return False
try:
# Get Python executable path
python_exe = sys.executable
if not python_exe:
python_exe = "python"
logging.info(f"Starting print service with: {python_exe} {service_script}")
# Start the service process
self.service_process = subprocess.Popen(
[python_exe, str(service_script), "--service"],
cwd=str(script_dir),
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1,
universal_newlines=True
)
# Monitor service output
def monitor_output():
if self.service_process:
for line in iter(self.service_process.stdout.readline, ''):
if line:
logging.info(f"Service: {line.strip()}")
if self.should_stop:
break
self.service_thread = threading.Thread(target=monitor_output, daemon=True)
self.service_thread.start()
logging.info("Print service started successfully")
return True
except Exception as e:
logging.error(f"Failed to start service: {e}")
return False
def stop_service(self):
"""Stop the print service."""
logging.info("Stopping print service...")
self.should_stop = True
if self.service_process:
try:
# Try graceful shutdown first
self.service_process.terminate()
# Wait up to 10 seconds for graceful shutdown
for _ in range(10):
if self.service_process.poll() is not None:
break
time.sleep(1)
# Force kill if still running
if self.service_process.poll() is None:
logging.warning("Force killing service process")
self.service_process.kill()
self.service_process.wait()
logging.info("Print service stopped")
except Exception as e:
logging.error(f"Error stopping service: {e}")
def run_service(self):
"""Main service loop."""
logging.info("Windows Print Service Wrapper starting...")
# Setup signal handlers
signal.signal(signal.SIGTERM, self.signal_handler)
signal.signal(signal.SIGINT, self.signal_handler)
if hasattr(signal, 'SIGBREAK'):
signal.signal(signal.SIGBREAK, self.signal_handler)
# Start the actual service
if not self.start_service():
logging.error("Failed to start print service")
return 1
# Service main loop - keep running until stopped
try:
while not self.should_stop:
# Check if service process is still running
if self.service_process and self.service_process.poll() is not None:
logging.warning("Service process died, restarting...")
if not self.start_service():
logging.error("Failed to restart service")
break
time.sleep(5) # Check every 5 seconds
except KeyboardInterrupt:
logging.info("Service interrupted by user")
except Exception as e:
logging.error(f"Service loop error: {e}")
finally:
self.stop_service()
logging.info("Windows Print Service Wrapper stopped")
return 0
def main():
"""Main entry point."""
service_manager = WindowsServiceManager()
service_manager.setup_logging()
# Check command line arguments
if len(sys.argv) > 1:
if sys.argv[1] == "install":
logging.info("Service install requested - use install_service_complete.bat instead")
return 1
elif sys.argv[1] == "start":
logging.info("Service start requested")
elif sys.argv[1] == "stop":
logging.info("Service stop requested")
return 0
# Run the service
return service_manager.run_service()
if __name__ == "__main__":
sys.exit(main())