259 lines
8.8 KiB
Python
259 lines
8.8 KiB
Python
"""
|
|
Windows Service Implementation - Alternative Approach
|
|
Uses Windows Task Scheduler as fallback if SC service fails
|
|
"""
|
|
|
|
import sys
|
|
import os
|
|
import subprocess
|
|
import time
|
|
import logging
|
|
from pathlib import Path
|
|
|
|
def create_scheduled_task_service():
|
|
"""Create Windows service using Task Scheduler as fallback."""
|
|
|
|
service_name = "QualityPrintService"
|
|
service_script = Path(__file__).parent / "print_service_complete.py"
|
|
python_exe = sys.executable
|
|
|
|
# Create XML for scheduled task
|
|
task_xml = f'''<?xml version="1.0" encoding="UTF-16"?>
|
|
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
|
|
<RegistrationInfo>
|
|
<Date>2025-09-26T12:00:00</Date>
|
|
<Author>Quality Print Service</Author>
|
|
<Description>Quality Print Service - Automatic Label Printing</Description>
|
|
</RegistrationInfo>
|
|
<Triggers>
|
|
<BootTrigger>
|
|
<Enabled>true</Enabled>
|
|
</BootTrigger>
|
|
</Triggers>
|
|
<Principals>
|
|
<Principal id="Author">
|
|
<UserId>S-1-5-18</UserId>
|
|
<RunLevel>HighestAvailable</RunLevel>
|
|
</Principal>
|
|
</Principals>
|
|
<Settings>
|
|
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
|
|
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
|
|
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
|
|
<AllowHardTerminate>true</AllowHardTerminate>
|
|
<StartWhenAvailable>true</StartWhenAvailable>
|
|
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
|
|
<IdleSettings>
|
|
<StopOnIdleEnd>false</StopOnIdleEnd>
|
|
<RestartOnIdle>false</RestartOnIdle>
|
|
</IdleSettings>
|
|
<AllowStartOnDemand>true</AllowStartOnDemand>
|
|
<Enabled>true</Enabled>
|
|
<Hidden>false</Hidden>
|
|
<RunOnlyIfIdle>false</RunOnlyIfIdle>
|
|
<WakeToRun>false</WakeToRun>
|
|
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
|
|
<Priority>7</Priority>
|
|
<RestartOnFailure>
|
|
<Interval>PT5M</Interval>
|
|
<Count>3</Count>
|
|
</RestartOnFailure>
|
|
</Settings>
|
|
<Actions Context="Author">
|
|
<Exec>
|
|
<Command>"{python_exe}"</Command>
|
|
<Arguments>"{service_script}" --service</Arguments>
|
|
<WorkingDirectory>{service_script.parent}</WorkingDirectory>
|
|
</Exec>
|
|
</Actions>
|
|
</Task>'''
|
|
|
|
# Save task XML to file
|
|
task_xml_file = Path(__file__).parent / f"{service_name}_task.xml"
|
|
with open(task_xml_file, 'w', encoding='utf-16') as f:
|
|
f.write(task_xml)
|
|
|
|
return task_xml_file
|
|
|
|
def install_service_alternative():
|
|
"""Install service using multiple methods."""
|
|
|
|
print("🔧 Installing Windows Print Service with Multiple Methods...")
|
|
|
|
service_name = "QualityPrintService"
|
|
service_display_name = "Quality Print Service"
|
|
service_script = Path(__file__).parent / "print_service_complete.py"
|
|
python_exe = sys.executable
|
|
|
|
# Method 1: Try SC command with service wrapper
|
|
print("\n📋 Method 1: Windows SC Service")
|
|
try:
|
|
# Create service wrapper batch file
|
|
wrapper_bat = Path(__file__).parent / "service_wrapper.bat"
|
|
|
|
wrapper_content = f'''@echo off
|
|
REM Windows Print Service Wrapper - Error 1053 Fix
|
|
cd /d "{service_script.parent}"
|
|
|
|
REM Set error handling
|
|
setlocal enabledelayedexpansion
|
|
|
|
REM Log startup
|
|
echo %date% %time% - Service starting... >> service_startup.log
|
|
|
|
REM Check if Python exists
|
|
if not exist "{python_exe}" (
|
|
echo ERROR: Python not found at {python_exe} >> service_startup.log
|
|
exit /b 1
|
|
)
|
|
|
|
REM Check if service script exists
|
|
if not exist "{service_script}" (
|
|
echo ERROR: Service script not found at {service_script} >> service_startup.log
|
|
exit /b 1
|
|
)
|
|
|
|
REM Start the service with timeout monitoring
|
|
echo Starting service process... >> service_startup.log
|
|
"{python_exe}" "{service_script}" --service
|
|
|
|
REM Log exit
|
|
echo %date% %time% - Service exited with code %errorlevel% >> service_startup.log
|
|
'''
|
|
|
|
with open(wrapper_bat, 'w') as f:
|
|
f.write(wrapper_content)
|
|
|
|
# Remove existing service
|
|
subprocess.run(['sc', 'stop', service_name], capture_output=True)
|
|
subprocess.run(['sc', 'delete', service_name], capture_output=True)
|
|
|
|
# Create service
|
|
cmd = [
|
|
'sc', 'create', service_name,
|
|
f'binPath= "{wrapper_bat}"',
|
|
f'DisplayName= "{service_display_name}"',
|
|
'start= auto'
|
|
]
|
|
|
|
result = subprocess.run(cmd, capture_output=True, text=True)
|
|
|
|
if result.returncode == 0:
|
|
print("✅ SC Service created successfully")
|
|
|
|
# Configure recovery
|
|
subprocess.run([
|
|
'sc', 'failure', service_name,
|
|
'reset= 86400',
|
|
'actions= restart/5000/restart/5000/restart/5000'
|
|
], capture_output=True)
|
|
|
|
# Try to start
|
|
start_result = subprocess.run(['sc', 'start', service_name], capture_output=True, text=True)
|
|
if start_result.returncode == 0:
|
|
print("✅ SC Service started successfully")
|
|
return True
|
|
else:
|
|
print(f"⚠️ SC Service created but failed to start: {start_result.stderr}")
|
|
else:
|
|
print(f"❌ SC Service creation failed: {result.stderr}")
|
|
|
|
except Exception as e:
|
|
print(f"❌ SC Service method failed: {e}")
|
|
|
|
# Method 2: Task Scheduler fallback
|
|
print("\n📋 Method 2: Task Scheduler Service")
|
|
try:
|
|
task_xml_file = create_scheduled_task_service()
|
|
|
|
# Remove existing task
|
|
subprocess.run(['schtasks', '/delete', '/tn', service_name, '/f'], capture_output=True)
|
|
|
|
# Create task
|
|
cmd = [
|
|
'schtasks', '/create', '/tn', service_name,
|
|
'/xml', str(task_xml_file)
|
|
]
|
|
|
|
result = subprocess.run(cmd, capture_output=True, text=True)
|
|
|
|
if result.returncode == 0:
|
|
print("✅ Task Scheduler service created successfully")
|
|
|
|
# Start task
|
|
start_result = subprocess.run(['schtasks', '/run', '/tn', service_name], capture_output=True, text=True)
|
|
if start_result.returncode == 0:
|
|
print("✅ Task Scheduler service started successfully")
|
|
return True
|
|
else:
|
|
print(f"⚠️ Task created but failed to start: {start_result.stderr}")
|
|
else:
|
|
print(f"❌ Task Scheduler creation failed: {result.stderr}")
|
|
|
|
except Exception as e:
|
|
print(f"❌ Task Scheduler method failed: {e}")
|
|
|
|
# Method 3: Manual startup script
|
|
print("\n📋 Method 3: Startup Script")
|
|
try:
|
|
startup_script = Path(os.environ.get('APPDATA', '')) / 'Microsoft' / 'Windows' / 'Start Menu' / 'Programs' / 'Startup' / 'QualityPrintService.bat'
|
|
startup_script.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
startup_content = f'''@echo off
|
|
REM Quality Print Service - Startup Script
|
|
cd /d "{service_script.parent}"
|
|
start /min "Quality Print Service" "{python_exe}" "{service_script}" --service
|
|
'''
|
|
|
|
with open(startup_script, 'w') as f:
|
|
f.write(startup_content)
|
|
|
|
print(f"✅ Startup script created: {startup_script}")
|
|
print("🔄 Service will start automatically on next reboot")
|
|
|
|
# Start immediately
|
|
subprocess.run(['cmd', '/c', str(startup_script)], capture_output=True)
|
|
print("✅ Service started via startup script")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"❌ Startup script method failed: {e}")
|
|
|
|
print("\n❌ All installation methods failed")
|
|
return False
|
|
|
|
def test_service_connection(timeout=10):
|
|
"""Test if service is running by checking HTTP endpoint."""
|
|
import urllib.request
|
|
import json
|
|
|
|
for i in range(timeout):
|
|
try:
|
|
with urllib.request.urlopen('http://localhost:8765/health', timeout=2) as response:
|
|
data = json.loads(response.read().decode())
|
|
if data.get('status') == 'healthy':
|
|
return True
|
|
except:
|
|
pass
|
|
time.sleep(1)
|
|
|
|
return False
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) > 1 and sys.argv[1] == 'install':
|
|
success = install_service_alternative()
|
|
|
|
if success:
|
|
print("\n🧪 Testing service connection...")
|
|
if test_service_connection():
|
|
print("✅ Service is responding correctly!")
|
|
print("🌐 Test URL: http://localhost:8765/health")
|
|
else:
|
|
print("⚠️ Service installed but not responding")
|
|
print("📋 Check logs and try manual start")
|
|
else:
|
|
print("\n❌ Service installation failed")
|
|
print("📋 Try running as Administrator")
|
|
sys.exit(1)
|
|
else:
|
|
print("Usage: python service_installer.py install") |