updated
This commit is contained in:
259
windows_print_service/service_installer.py
Normal file
259
windows_print_service/service_installer.py
Normal file
@@ -0,0 +1,259 @@
|
||||
"""
|
||||
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")
|
||||
Reference in New Issue
Block a user