updated
This commit is contained in:
175
windows_print_service/service_wrapper.py
Normal file
175
windows_print_service/service_wrapper.py
Normal 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())
|
||||
Reference in New Issue
Block a user