diff --git a/py_app/PRINT_SERVICE_SETUP.md b/py_app/PRINT_SERVICE_SETUP.md deleted file mode 100644 index 9a31eff..0000000 --- a/py_app/PRINT_SERVICE_SETUP.md +++ /dev/null @@ -1,74 +0,0 @@ -# Windows Print Service Network Configuration Guide - -## Current Issue -Your Flask server (Linux) cannot connect to Windows Print Service because they're on different machines. - -## Solution Options - -### Option 1: Same Machine Setup -If both Flask and Windows service are on the same machine: -```python -WINDOWS_PRINT_SERVICE_URL = "http://localhost:8765" -``` - -### Option 2: Different Machines (Recommended) -If Flask server (Linux) and Windows service are on different machines: - -1. **Find Windows Machine IP Address:** - ```cmd - # On Windows machine, run: - ipconfig - # Look for IPv4 Address, e.g., 192.168.1.100 - ``` - -2. **Update Configuration:** - ```python - # In /app/print_config.py, change: - WINDOWS_PRINT_SERVICE_URL = "http://192.168.1.100:8765" - ``` - -3. **Test Connection:** - ```bash - # From Linux machine, test: - curl http://192.168.1.100:8765/health - ``` - -### Option 3: Windows Firewall Configuration -Ensure Windows allows incoming connections on port 8765: - -1. **Windows Firewall Settings:** - - Control Panel → System and Security → Windows Defender Firewall - - Advanced Settings → Inbound Rules → New Rule - - Port → TCP → 8765 → Allow the connection - -2. **Test from Linux:** - ```bash - telnet [WINDOWS_IP] 8765 - ``` - -### Option 4: Port Forwarding/Tunneling -If direct connection isn't possible, set up SSH tunnel or port forwarding. - -## Quick Fix for Testing - -1. **Get Windows IP Address** -2. **Update print_config.py with the IP** -3. **Restart Flask server** -4. **Test printing** - -## Current Status -- ✅ Windows Print Service: Running (localhost:8765/health works) -- ❌ Network Connection: Flask can't reach Windows service -- 🔧 Fix Needed: Update WINDOWS_PRINT_SERVICE_URL with correct IP - -## Example Commands - -```bash -# 1. Find Windows IP (run on Windows): -# ipconfig | findstr IPv4 - -# 2. Test connection (run on Linux): -# curl http://[WINDOWS_IP]:8765/health - -# 3. Update config and restart Flask -``` \ No newline at end of file diff --git a/py_app/analyze_pdf_dimensions.py b/py_app/analyze_pdf_dimensions.py deleted file mode 100644 index 4a5a45d..0000000 --- a/py_app/analyze_pdf_dimensions.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/env python3 -""" -PDF Label Dimension Analysis Tool -Analyzes the generated PDF to verify exact dimensions and content positioning -""" - -import sys -import os -sys.path.append(os.path.join(os.path.dirname(__file__), 'app')) - -from app.pdf_generator import LabelPDFGenerator, mm_to_points -from reportlab.lib.units import mm - -def analyze_pdf_dimensions(): - """Analyze the PDF dimensions in detail""" - print("=== PDF Label Dimension Analysis ===\n") - - generator = LabelPDFGenerator() - - # Label dimensions - print("1. LABEL PHYSICAL DIMENSIONS:") - print(f" Width: {generator.label_width/mm:.1f}mm ({generator.label_width:.2f} points)") - print(f" Height: {generator.label_height/mm:.1f}mm ({generator.label_height:.2f} points)") - print(f" ✓ Should be exactly 80.0mm × 110.0mm") - - # Content area - print(f"\n2. CONTENT AREA DIMENSIONS:") - print(f" Content Width: {generator.content_width/mm:.1f}mm") - print(f" Content Height: {generator.content_height/mm:.1f}mm") - print(f" Left margin: {generator.content_x/mm:.1f}mm") - print(f" Bottom margin: {generator.content_y/mm:.1f}mm") - print(f" Right margin: {(generator.label_width - generator.content_x - generator.content_width)/mm:.1f}mm") - print(f" Top margin: {(generator.label_height - generator.content_y - generator.content_height)/mm:.1f}mm") - - # Row analysis - print(f"\n3. ROW LAYOUT:") - total_rows = 9 - standard_rows = 8 # 7 standard + 1 double - double_rows = 1 - - standard_row_height_mm = generator.row_height/mm - double_row_height_mm = generator.double_row_height/mm - - total_content_used = (standard_rows * standard_row_height_mm + double_rows * double_row_height_mm) - expected_content_height = generator.content_height/mm - - print(f" Standard row height: {standard_row_height_mm:.1f}mm") - print(f" Double row height: {double_row_height_mm:.1f}mm") - print(f" Total rows: {total_rows} (8 standard + 1 double)") - print(f" Content height used: {total_content_used:.1f}mm") - print(f" Content area available: {expected_content_height:.1f}mm") - print(f" Remaining space: {expected_content_height - total_content_used:.1f}mm") - - # Barcode area - print(f"\n4. BARCODE AREA:") - barcode_bottom_margin = generator.content_y/mm - print(f" Bottom barcode space: {barcode_bottom_margin:.1f}mm (should be ~12-15mm)") - - top_margin = (generator.label_height - generator.content_y - generator.content_height)/mm - print(f" Top margin space: {top_margin:.1f}mm") - - # Check for potential issues - print(f"\n5. POTENTIAL ISSUES ANALYSIS:") - - # Check if content is too high - if total_content_used > expected_content_height: - print(f" ⚠️ ISSUE: Content ({total_content_used:.1f}mm) exceeds available space ({expected_content_height:.1f}mm)") - else: - print(f" ✓ Content fits within available space") - - # Check margins - if barcode_bottom_margin < 10: - print(f" ⚠️ WARNING: Bottom margin ({barcode_bottom_margin:.1f}mm) may be too small for barcode") - else: - print(f" ✓ Bottom margin adequate for barcode") - - if top_margin < 3: - print(f" ⚠️ WARNING: Top margin ({top_margin:.1f}mm) very small") - else: - print(f" ✓ Top margin adequate") - - # Aspect ratio check - aspect_ratio = generator.label_height / generator.label_width - expected_ratio = 110.0 / 80.0 # 1.375 - - print(f"\n6. ASPECT RATIO CHECK:") - print(f" Current ratio: {aspect_ratio:.3f}") - print(f" Expected ratio: {expected_ratio:.3f} (110/80)") - - if abs(aspect_ratio - expected_ratio) < 0.001: - print(f" ✓ Aspect ratio is correct") - else: - print(f" ⚠️ Aspect ratio mismatch!") - - # Browser display notes - print(f"\n7. BROWSER DISPLAY CONSIDERATIONS:") - print(f" • Browser zoom affects apparent size") - print(f" • PDF viewer scaling can change appearance") - print(f" • Monitor DPI affects screen dimensions") - print(f" • Print preview scaling may alter appearance") - print(f"\n 🔧 SOLUTION: Always verify with physical printout at 100% scale") - - return { - 'width_mm': generator.label_width/mm, - 'height_mm': generator.label_height/mm, - 'content_height_mm': expected_content_height, - 'content_used_mm': total_content_used, - 'aspect_ratio': aspect_ratio, - 'expected_ratio': expected_ratio - } - -if __name__ == "__main__": - results = analyze_pdf_dimensions() - - print(f"\n=== SUMMARY ===") - if (abs(results['width_mm'] - 80.0) < 0.1 and - abs(results['height_mm'] - 110.0) < 0.1 and - abs(results['aspect_ratio'] - results['expected_ratio']) < 0.001): - print("✅ PDF dimensions are CORRECT: 80mm × 110mm") - print("If labels appear too large, check:") - print(" • Browser zoom level (should be 100%)") - print(" • PDF viewer scaling settings") - print(" • Print scaling (should be 'Actual size' or 100%)") - else: - print("❌ PDF dimensions need adjustment") \ No newline at end of file diff --git a/py_app/app/__pycache__/routes.cpython-312.pyc b/py_app/app/__pycache__/routes.cpython-312.pyc index a6e3107..e2ff6de 100644 Binary files a/py_app/app/__pycache__/routes.cpython-312.pyc and b/py_app/app/__pycache__/routes.cpython-312.pyc differ diff --git a/py_app/app/routes.py b/py_app/app/routes.py index 2244461..ab9e18a 100644 --- a/py_app/app/routes.py +++ b/py_app/app/routes.py @@ -2065,6 +2065,47 @@ def update_printed_status(order_id): print(f"DEBUG: Error in update_printed_status: {e}") return jsonify({'error': 'Internal server error'}), 500 + +@bp.route('/download_print_service') +def download_print_service(): + """Download the direct print service package""" + try: + from flask import send_from_directory, current_app + import os + + # Check if complete package is requested + package_type = request.args.get('package', 'basic') + + if package_type == 'complete': + # Serve the complete package + filename = 'QualityPrintService_Complete.zip' + else: + # Serve the basic package (legacy) + filename = 'RecticelPrintService.zip' + + # Path to the print service files + service_path = os.path.join(current_app.root_path, 'static', 'downloads') + + # Create the directory if it doesn't exist + os.makedirs(service_path, exist_ok=True) + + # Check if the zip file exists + full_path = os.path.join(service_path, filename) + + if not os.path.exists(full_path): + # If the zip doesn't exist, return information about creating it + return jsonify({ + 'error': f'Print service package ({filename}) not found', + 'message': f'The {package_type} print service package is not available', + 'suggestion': 'Please contact the administrator or use the basic package' + }), 404 + + return send_from_directory(service_path, filename, as_attachment=True) + + except Exception as e: + print(f"DEBUG: Error downloading print service: {e}") + return jsonify({'error': 'Failed to download print service'}), 500 + @bp.route('/get_order_data/', methods=['GET']) def get_order_data(order_id): """Get specific order data for preview""" diff --git a/py_app/app/templates/print_module.html b/py_app/app/templates/print_module.html index afc0054..9ba770f 100644 --- a/py_app/app/templates/print_module.html +++ b/py_app/app/templates/print_module.html @@ -204,6 +204,25 @@
Creates sequential labels based on quantity
(e.g., CP00000711-001 to CP00000711-063) + + +
+
+
+ 📦 Quality Print Service +
+
+ Professional Windows service for instant direct printing to thermal label printers without PDF dialogs +
+ + 📥 Download Complete Package + +
+
+ Easy Install: Extract → Run install.bat as Admin → Done!
+ Supports all thermal printers • Auto-starts with Windows • One-click installation +
+
@@ -330,6 +349,9 @@ document.getElementById('check-db-btn').addEventListener('click', function() { // Initialize PDF generation functionality addPDFGenerationHandler(); + // Initialize print service + initializePrintService(); + // Auto-select first row setTimeout(() => { const firstRow = document.querySelector('.print-module-table tbody tr'); @@ -396,6 +418,96 @@ function updateLabelPreview(order) { document.getElementById('barcode-text').textContent = prodOrder; } +// Initialize print service connection and load available printers +function initializePrintService() { + // Check service status and load printers + checkPrintServiceStatus() + .then(serviceStatus => { + if (serviceStatus) { + console.log('✅ Print service is available'); + loadAvailablePrinters(); + updateServiceStatusIndicator(true); + } else { + console.log('⚠️ Print service not available'); + updateServiceStatusIndicator(false); + } + }) + .catch(error => { + console.log('❌ Print service connection failed:', error); + updateServiceStatusIndicator(false); + }); +} + +// Load available printers from print service +function loadAvailablePrinters() { + fetch('http://localhost:8899/printers', { + method: 'GET', + mode: 'cors' + }) + .then(response => response.json()) + .then(data => { + const printerSelect = document.getElementById('printerSelect'); + + // Clear existing options except default ones + const defaultOptions = ['default', 'Epson TM-T20', 'Citizen CTS-310', 'custom']; + Array.from(printerSelect.options).forEach(option => { + if (!defaultOptions.includes(option.value)) { + option.remove(); + } + }); + + // Add available printers + if (data.printers && data.printers.length > 0) { + data.printers.forEach(printer => { + // Don't add if already exists in default options + if (!defaultOptions.includes(printer.name)) { + const option = document.createElement('option'); + option.value = printer.name; + option.textContent = `${printer.name}${printer.default ? ' (Default)' : ''}${printer.status !== 'ready' ? ' - Offline' : ''}`; + + // Insert before "Other Printer..." option + const customOption = printerSelect.querySelector('option[value="custom"]'); + printerSelect.insertBefore(option, customOption); + } + }); + + // Set default printer if available + const defaultPrinter = data.printers.find(p => p.default); + if (defaultPrinter) { + printerSelect.value = defaultPrinter.name; + } + } + + console.log(`Loaded ${data.printers.length} printers from service`); + }) + .catch(error => { + console.log('Could not load printers from service:', error); + }); +} + +// Update service status indicator +function updateServiceStatusIndicator(isAvailable) { + // Find or create status indicator + let statusIndicator = document.getElementById('service-status-indicator'); + if (!statusIndicator) { + statusIndicator = document.createElement('div'); + statusIndicator.id = 'service-status-indicator'; + statusIndicator.style.cssText = 'font-size: 9px; color: #6c757d; margin-top: 5px; text-align: center;'; + + // Insert after printer selection + const printerSelection = document.getElementById('printerSelection'); + printerSelection.appendChild(statusIndicator); + } + + if (isAvailable) { + statusIndicator.innerHTML = '🟢 Print service connected
Direct printing available'; + statusIndicator.style.color = '#28a745'; + } else { + statusIndicator.innerHTML = '🔴 Print service offline
Install and start the service for direct printing'; + statusIndicator.style.color = '#dc3545'; + } +} + // PDF Generation System - No printer setup needed // Labels are generated as PDF files for universal compatibility function addPDFGenerationHandler() { @@ -463,67 +575,114 @@ function handleDirectPrint(selectedRow) { printerName = prompt('Enter your printer name:'); if (!printerName) return; } else if (printerName === 'default') { - printerName = 'default'; + printerName = ''; // Empty for default printer } - console.log(`Direct printing to: ${printerName}`); + console.log(`Direct printing to: ${printerName || 'default printer'}`); - // Extract order data from selected row - const cells = selectedRow.querySelectorAll('td'); - const orderData = { - order_id: parseInt(orderId), - comanda_productie: cells[1].textContent.trim(), - cod_articol: cells[2].textContent.trim(), - descr_com_prod: cells[3].textContent.trim(), - cantitate: parseInt(cells[4].textContent.trim()), - data_livrare: cells[5].textContent.trim(), - dimensiune: cells[6].textContent.trim(), - com_achiz_client: cells[7].textContent.trim(), - nr_linie_com_client: cells[8].textContent.trim(), - customer_name: cells[9].textContent.trim(), - customer_article_number: cells[10].textContent.trim() - }; - - // Print each label individually - for (let i = 1; i <= quantity; i++) { - const labelData = { - ...orderData, - sequential_number: `${orderData.comanda_productie}-${i.toString().padStart(3, '0')}`, - current_label: i, - total_labels: quantity - }; - - // Encode data as base64 JSON - const jsonString = JSON.stringify(labelData); - const base64Data = btoa(unescape(encodeURIComponent(jsonString))); - - // Create custom protocol URL - const printUrl = `recticel-print://${encodeURIComponent(printerName)}/${base64Data}`; - - console.log(`Printing label ${i}/${quantity}: ${printUrl.substring(0, 100)}...`); - - // Trigger direct print via custom protocol - try { - window.location.href = printUrl; - } catch (error) { - console.error(`Failed to print label ${i}:`, error); - alert(`❌ Failed to print label ${i}/${quantity}. Please check if the print service is installed.`); - return; + // Check if print service is available + checkPrintServiceStatus() + .then(serviceStatus => { + if (!serviceStatus) { + throw new Error('Print service is not available'); + } + + // Generate PDF first for printing + return generatePrintablePDF(orderId, true); // true for paper-saving mode + }) + .then(pdfUrl => { + // Send PDF to print service + const printData = { + pdf_url: pdfUrl, + printer: printerName, + copies: 1, + order_id: parseInt(orderId), + paper_saving: true + }; + + return fetch('http://localhost:8899/print-pdf', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(printData) + }); + }) + .then(response => { + if (!response.ok) { + throw new Error(`Print service error: ${response.status}`); + } + return response.json(); + }) + .then(result => { + if (result.success) { + alert(`✅ Successfully sent ${quantity} labels to printer!\n📊 Order: ${prodOrder}\n🖨️ Printer: ${printerName || 'Default'}\n📄 Job ID: ${result.job_id || 'N/A'}`); + + // Update database status and refresh table + updatePrintedStatus(orderId); + } else { + throw new Error(result.error || 'Unknown print error'); + } + }) + .catch(error => { + console.error('Direct print error:', error); + + let errorMessage = '❌ Direct printing failed: ' + error.message; + + if (error.message.includes('service is not available')) { + errorMessage += '\n\n💡 Solutions:\n' + + '1. Install the print service using the download link below\n' + + '2. Ensure the service is running (check Windows Services)\n' + + '3. Try restarting the print service\n' + + '4. Use PDF generation as alternative'; + } else if (error.message.includes('fetch')) { + errorMessage += '\n\n💡 The print service may not be running.\n' + + 'Please start the Quality Print Service from Windows Services.'; + } + + alert(errorMessage); + }); +} + +// Helper function to check print service status +function checkPrintServiceStatus() { + return fetch('http://localhost:8899/status', { + method: 'GET', + mode: 'cors' + }) + .then(response => { + if (response.ok) { + return response.json().then(data => { + console.log('Print service status:', data); + return data.status === 'running'; + }); } - - // Small delay between labels to prevent overwhelming the printer - if (i < quantity) { - setTimeout(() => {}, 100); + return false; + }) + .catch(error => { + console.log('Print service not available:', error.message); + return false; + }); +} + +// Helper function to generate PDF for printing +function generatePrintablePDF(orderId, paperSaving = true) { + return fetch(`/generate_labels_pdf/${orderId}/${paperSaving ? 'true' : 'false'}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' } - } - - // Show success message - setTimeout(() => { - alert(`✅ Sent ${quantity} labels to printer: ${printerName}\n📊 Order: ${prodOrder}`); - - // Update database status and refresh table - updatePrintedStatus(orderId); - }, 500); + }) + .then(response => { + if (!response.ok) { + throw new Error(`Failed to generate PDF: ${response.status}`); + } + return response.blob(); + }) + .then(blob => { + // Create a temporary URL for the PDF + return URL.createObjectURL(blob); + }); } function handlePDFGeneration(selectedRow) { diff --git a/py_app/documentation.md b/py_app/documentation.md deleted file mode 100644 index 46a17e7..0000000 --- a/py_app/documentation.md +++ /dev/null @@ -1,422 +0,0 @@ -# Quality Control Management System - Documentation - -## Table of Contents -1. [Login System](#login-system) -2. [Dashboard System](#dashboard-system) -3. [User Authentication](#user-authentication) -4. [Role-Based Access Control](#role-based-access-control) - ---- - -## Login System - -### Overview -The Quality Control Management System features a dual-database authentication system that provides flexible user management and robust access control. The login system supports both internal SQLite database users and external MariaDB database users. - -### Authentication Flow - -#### 1. Login Page Access -- **URL**: `/login` -- **Template**: `login.html` -- **Methods**: `GET`, `POST` - -#### 2. User Interface -The login page features: -- **Company Logo**: Displayed prominently on the left side -- **Login Form**: Clean, centered form on the right side -- **Required Fields**: - - Username (text input) - - Password (password input) -- **Responsive Design**: Adapts to different screen sizes - -#### 3. Authentication Methods - -##### Internal Database Authentication -Users can access the system using the internal SQLite database by prefixing their username with `#`: - -**Format**: `#username` -**Example**: `#admin` for internal admin user - -**Database Details**: -- **Location**: `py_app/instance/users.db` -- **Table**: `users` -- **Schema**: `username, password, role` -- **Use Case**: System administrators, fallback authentication - -##### External Database Authentication -Standard authentication uses the external MariaDB database: - -**Format**: `username` (no prefix) -**Example**: `john.doe` for external user - -**Database Details**: -- **Type**: MariaDB -- **Configuration**: Loaded from `external_database_settings` -- **Table**: `users` -- **Schema**: `username, password, role` -- **Use Case**: Regular operational users - -#### 4. Authentication Logic - -```python -# Authentication Process Flow -if username.startswith('#'): - # Internal SQLite Database Authentication - username_clean = username[1:].strip() - # Query: py_app/instance/users.db - -else: - # External MariaDB Database Authentication - # Primary: External database query - # Fallback: Internal database if external fails -``` - -#### 5. Security Features - -##### Input Validation -- **Required Fields**: Both username and password must be provided -- **Sanitization**: Automatic trimming of whitespace -- **Error Handling**: Clear error messages for invalid inputs - -##### Database Connection Security -- **Dual Fallback**: External database with internal fallback -- **Error Isolation**: Database errors don't expose system details -- **Connection Management**: Proper connection opening/closing - -##### Session Management -- **Secure Sessions**: User credentials stored in Flask session -- **Role Tracking**: User role preserved for authorization -- **Session Data**: - - `session['user']`: Username - - `session['role']`: User role - -#### 6. User Roles - -The system supports multiple user roles with different access levels: - -- **superadmin**: Full system access, all modules and administrative functions -- **admin**: Administrative access with some limitations -- **quality**: Quality control module access -- **warehouse**: Warehouse management module access -- **scan**: Scanning operations access -- **etichete**: Label management access -- **management**: Management reporting and oversight - -#### 7. Login Process - -1. **User Navigation**: User accesses `/login` URL -2. **Form Display**: Login form rendered with company branding -3. **Credential Submission**: User enters username/password and submits -4. **Authentication Check**: - - Internal users: Check SQLite database - - External users: Check MariaDB database with SQLite fallback -5. **Session Creation**: Valid credentials create user session -6. **Redirect**: Successful login redirects to `/dashboard` -7. **Error Handling**: Invalid credentials display error message - -#### 8. Error Messages - -- **Missing Credentials**: "Please enter both username and password." -- **Invalid Credentials**: "Invalid credentials. Please try again." -- **Database Errors**: Handled gracefully with fallback mechanisms - -#### 9. Post-Login Behavior - -After successful authentication: -- **Session Establishment**: User session created with username and role -- **Dashboard Redirect**: User redirected to main dashboard -- **Access Control**: Role-based permissions applied throughout system -- **Navigation**: Header displays logged-in user information - -#### 10. Security Considerations - -##### Password Security -- **Storage**: Passwords stored in plaintext (consider encryption upgrade) -- **Transmission**: Form-based submission over HTTPS recommended -- **Session**: Password not stored in session, only username/role - -##### Database Security -- **Connection Strings**: External database settings in separate config -- **Error Handling**: Database errors logged but not exposed to users -- **Fallback System**: Ensures availability even if external database fails - -### Technical Implementation - -#### Frontend Components -- **Template**: `templates/login.html` -- **Styling**: Login-specific CSS in `static/style.css` -- **Assets**: Company logo (`static/logo_login.jpg`) - -#### Backend Components -- **Route Handler**: `@bp.route('/login', methods=['GET', 'POST'])` -- **Database Connections**: SQLite and MariaDB integration -- **Session Management**: Flask session handling -- **Error Handling**: Comprehensive exception management - -#### Configuration Files -- **External Database**: Configuration loaded from `external_database_settings` -- **Internal Database**: SQLite database in `instance/users.db` - -### Usage Examples - -#### Standard User Login -``` -Username: john.doe -Password: userpassword -Result: Queries external MariaDB database -``` - -#### Internal Admin Login -``` -Username: #admin -Password: adminpassword -Result: Queries internal SQLite database -``` - -#### System Administrator Login -``` -Username: #superadmin -Password: superpass -Result: Internal database, full system access -``` - ---- - -## Dashboard System - -### Overview -The dashboard serves as the central hub of the Quality Control Management System, providing authenticated users with access to various system modules based on their assigned roles. It features a clean, card-based interface that displays available modules and ensures proper access control. - -### Dashboard Access - -#### 1. Dashboard Page Access -- **URL**: `/dashboard` -- **Template**: `dashboard.html` -- **Methods**: `GET` -- **Authentication Required**: Yes (redirects to login if not authenticated) - -#### 2. User Interface Design - -The dashboard features a modern, responsive card-based layout: -- **Container**: Full-width responsive grid layout -- **Module Cards**: Individual cards for each system module -- **Visual Hierarchy**: Clear headings, descriptions, and call-to-action buttons -- **Responsive Design**: Adapts to different screen sizes and devices - -#### 3. Available Modules - -##### Scanning Module -- **Card Title**: "Access Scanning Module" -- **Description**: "Final scanning module for production orders" -- **Button**: "Launch Scanning Module" -- **Route**: `/scan` -- **Required Roles**: `superadmin`, `scan` -- **Purpose**: Quality control scanning operations for production orders - -##### Reports Module (Quality) -- **Card Title**: "Access Reports Module" -- **Description**: "Module for verification and quality settings configuration" -- **Button**: "Launch Reports Module" -- **Route**: `/quality` -- **Required Roles**: `superadmin`, `quality` -- **Purpose**: Quality reporting, defects analysis, and quality control reports - -##### Warehouse Module -- **Card Title**: "Access Warehouse Module" -- **Description**: "Access warehouse module functionalities" -- **Button**: "Open Warehouse" -- **Route**: `/warehouse` -- **Required Roles**: `superadmin`, `warehouse` -- **Purpose**: Warehouse management operations and inventory control - -##### Labels Module -- **Card Title**: "Access Labels Module" -- **Description**: "Module for label management" -- **Button**: "Launch Labels Module" -- **Route**: `/etichete` -- **Required Roles**: `superadmin`, `etichete` -- **Purpose**: Label creation, template management, and printing operations - -##### Settings Module -- **Card Title**: "Manage Settings" -- **Description**: "Access and manage application settings" -- **Button**: "Access Settings Page" -- **Route**: `/settings` -- **Required Roles**: `superadmin` only -- **Purpose**: System configuration, user management, and administrative settings - -#### 4. Access Control Logic - -The dashboard implements role-based access control at both the display and route levels: - -##### Frontend Display Control -All module cards are displayed to all authenticated users, but access is controlled at the route level. - -##### Backend Route Protection -Each module route implements permission checking: - -```python -# Quality Module Access Control -@bp.route('/quality') -def quality(): - if 'role' not in session or session['role'] not in ['superadmin', 'quality']: - flash('Access denied: Quality users only.') - return redirect(url_for('main.dashboard')) - -# Warehouse Module Access Control -@bp.route('/warehouse') -def warehouse(): - if 'role' not in session or session['role'] not in ['superadmin', 'warehouse']: - flash('Access denied: Warehouse users only.') - return redirect(url_for('main.dashboard')) - -# Scanning Module Access Control -@bp.route('/scan') -def scan(): - if 'role' not in session or session['role'] not in ['superadmin', 'scan']: - flash('Access denied: Scan users only.') - return redirect(url_for('main.dashboard')) - -# Labels Module Access Control -@bp.route('/etichete') -def etichete(): - if 'role' not in session or session['role'] not in ['superadmin', 'etichete']: - flash('Access denied: Etichete users only.') - return redirect(url_for('main.dashboard')) - -# Settings Module Access Control (Superadmin Only) -def settings_handler(): - if 'role' not in session or session['role'] != 'superadmin': - flash('Access denied: Superadmin only.') - return redirect(url_for('main.dashboard')) -``` - -#### 5. User Experience Flow - -1. **Authentication Check**: User must be logged in to access dashboard -2. **Dashboard Display**: All module cards shown regardless of role -3. **Module Selection**: User clicks on desired module button -4. **Permission Validation**: System checks user role against module requirements -5. **Access Grant/Deny**: - - **Authorized**: User redirected to module interface - - **Unauthorized**: Error message displayed, user remains on dashboard - -#### 6. Session Management - -The dashboard relies on Flask session management: -- **Session Check**: `if 'user' not in session` validates authentication -- **Role Access**: `session['role']` determines module permissions -- **Debug Logging**: Session information logged for troubleshooting - -#### 7. Error Handling - -##### Authentication Errors -- **Unauthenticated Users**: Automatic redirect to login page -- **Session Timeout**: Redirect to login with appropriate messaging - -##### Authorization Errors -- **Insufficient Permissions**: Flash message with specific role requirements -- **Access Denied**: User returned to dashboard with error notification -- **Clear Messaging**: Specific error messages indicate required permissions - -#### 8. Security Features - -##### Session Security -- **Authentication Required**: All dashboard access requires valid session -- **Role Validation**: Each module validates user role before access -- **Automatic Redirect**: Unauthorized access redirected safely - -##### Access Control -- **Principle of Least Privilege**: Users only access modules for their role -- **Superadmin Override**: Superadmin role has access to all modules -- **Route-Level Protection**: Backend validation prevents unauthorized access - -#### 9. Module Descriptions - -##### Quality Reports Module -- **Primary Function**: Generate quality control reports and analytics -- **Key Features**: - - Daily, weekly, and custom date range reports - - Quality defects analysis and tracking - - Export capabilities (CSV format) - - Database testing tools (superadmin only) - -##### Scanning Module -- **Primary Function**: Production order scanning and quality validation -- **Key Features**: - - Barcode/QR code scanning interface - - Real-time quality validation - - Production order processing - -##### Warehouse Module -- **Primary Function**: Warehouse operations and inventory management -- **Key Features**: - - Inventory tracking and management - - Location management - - Warehouse reporting - -##### Labels Module -- **Primary Function**: Label design, generation, and printing -- **Key Features**: - - Label template creation and management - - Dynamic label generation - - Print management system - -##### Settings Module -- **Primary Function**: System administration and configuration -- **Key Features**: - - User account management - - Role and permission configuration - - Database settings management - - System configuration options - -#### 10. Technical Implementation - -##### Frontend Components -- **Template**: `templates/dashboard.html` -- **Styling**: Dashboard-specific CSS classes in `static/style.css` -- **Layout**: CSS Grid/Flexbox responsive card layout -- **Navigation**: Base template integration with header/footer - -##### Backend Components -- **Route Handler**: `@bp.route('/dashboard')` -- **Session Management**: Flask session integration -- **Authentication Check**: User session validation -- **Logging**: Debug output for troubleshooting - -##### Styling Classes -- `.dashboard-container`: Main container with responsive grid -- `.dashboard-card`: Individual module cards -- `.btn`: Standardized button styling -- Responsive breakpoints for mobile/tablet adaptation - -### Usage Examples - -#### Superadmin User Dashboard Access -``` -Role: superadmin -Available Modules: All (Scanning, Quality, Warehouse, Labels, Settings) -Special Access: Settings module exclusive access -``` - -#### Quality Control User Dashboard Access -``` -Role: quality -Available Modules: Quality Reports module only -Restricted Access: Cannot access other modules -``` - -#### Multi-Role Access Example -``` -Role: warehouse -Available Modules: Warehouse module only -Access Pattern: Click → Permission Check → Module Access -``` - ---- - -*This documentation covers the dashboard system implementation. For specific module details, see their respective documentation sections.* - - - - diff --git a/py_app/test_print_connection.py b/py_app/test_print_connection.py deleted file mode 100644 index deb26e5..0000000 --- a/py_app/test_print_connection.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env python3 -""" -Windows Print Service Connection Tester -Tests connectivity between Flask server and Windows Print Service -""" - -import sys -import os -sys.path.append(os.path.join(os.path.dirname(__file__), 'app')) - -import requests -import time -from app.print_config import WINDOWS_PRINT_SERVICE_URL, PRINT_SERVICE_TIMEOUT - -def test_print_service_connection(): - """Test connection to Windows Print Service""" - print("=== Windows Print Service Connection Test ===\n") - - print(f"🔍 Testing connection to: {WINDOWS_PRINT_SERVICE_URL}") - print(f"⏱️ Timeout: {PRINT_SERVICE_TIMEOUT} seconds") - print(f"🌐 From: Flask server (Linux)") - print(f"🎯 To: Windows Print Service") - print() - - # Test 1: Health check - print("1️⃣ Testing /health endpoint...") - try: - start_time = time.time() - response = requests.get( - f"{WINDOWS_PRINT_SERVICE_URL}/health", - timeout=PRINT_SERVICE_TIMEOUT - ) - elapsed = time.time() - start_time - - if response.status_code == 200: - data = response.json() - print(f" ✅ SUCCESS (Status: {response.status_code}, Time: {elapsed:.2f}s)") - print(f" 📋 Service: {data.get('service', 'Unknown')}") - print(f" 🖥️ Platform: {data.get('platform', 'Unknown')}") - print(f" 📅 Timestamp: {data.get('timestamp', 'Unknown')}") - health_ok = True - else: - print(f" ❌ FAILED (Status: {response.status_code})") - print(f" 📝 Response: {response.text}") - health_ok = False - except requests.exceptions.ConnectionError as e: - print(f" ❌ CONNECTION REFUSED") - print(f" 🔧 Error: {str(e)}") - print(f" 💡 This usually means:") - print(f" • Windows service is not running") - print(f" • Wrong IP address in configuration") - print(f" • Firewall blocking connection") - print(f" • Network routing issue") - health_ok = False - except Exception as e: - print(f" ❌ ERROR: {str(e)}") - health_ok = False - - print() - - # Test 2: Printers endpoint (only if health check passed) - if health_ok: - print("2️⃣ Testing /printers endpoint...") - try: - response = requests.get( - f"{WINDOWS_PRINT_SERVICE_URL}/printers", - timeout=PRINT_SERVICE_TIMEOUT - ) - if response.status_code == 200: - data = response.json() - printers = data.get('printers', []) - print(f" ✅ SUCCESS - Found {len(printers)} printer(s)") - for i, printer in enumerate(printers[:3]): # Show first 3 - name = printer.get('name', 'Unknown') if isinstance(printer, dict) else printer - print(f" 🖨️ {i+1}. {name}") - if len(printers) > 3: - print(f" ... and {len(printers)-3} more") - else: - print(f" ❌ FAILED (Status: {response.status_code})") - except Exception as e: - print(f" ❌ ERROR: {str(e)}") - - print() - - # Test 3: Network diagnostics - print("3️⃣ Network Diagnostics...") - - # Parse URL to get host and port - try: - from urllib.parse import urlparse - parsed = urlparse(WINDOWS_PRINT_SERVICE_URL) - host = parsed.hostname - port = parsed.port or 8765 - - print(f" 🌐 Target Host: {host}") - print(f" 🔌 Target Port: {port}") - - # Test DNS resolution - try: - import socket - ip = socket.gethostbyname(host) - print(f" 🔍 DNS Resolution: {host} → {ip}") - dns_ok = True - except Exception as e: - print(f" ❌ DNS Resolution failed: {e}") - dns_ok = False - - # Test raw TCP connection - if dns_ok: - try: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(5) - result = sock.connect_ex((host, port)) - sock.close() - - if result == 0: - print(f" ✅ TCP Connection: Port {port} is open") - else: - print(f" ❌ TCP Connection: Port {port} is closed or filtered") - print(f" 💡 Check Windows Firewall and service status") - except Exception as e: - print(f" ❌ TCP Test error: {e}") - except Exception as e: - print(f" ❌ URL parsing error: {e}") - - print() - - # Final recommendations - print("🔧 TROUBLESHOOTING RECOMMENDATIONS:") - print() - - if not health_ok: - print("❌ CONNECTION FAILED - Try these steps:") - print("1. Verify Windows Print Service is running:") - print(" • Windows: sc query QualityLabelPrinting") - print(" • Or: Get-Service QualityLabelPrinting") - print() - print("2. Check Windows machine IP address:") - print(" • Windows: ipconfig | findstr IPv4") - print(" • Update WINDOWS_PRINT_SERVICE_URL in print_config.py") - print() - print("3. Test firewall:") - print(" • Windows: Allow port 8765 in Windows Firewall") - print(" • Test: telnet [WINDOWS_IP] 8765") - print() - print("4. If same machine, verify service binding:") - print(" • Service should bind to 0.0.0.0:8765 (not 127.0.0.1)") - else: - print("✅ CONNECTION SUCCESS - Print service should work!") - print("• Service is reachable and responding") - print("• Ready for label printing") - print("• Try printing labels from the web interface") - - print(f"\n📝 Current Configuration:") - print(f" Service URL: {WINDOWS_PRINT_SERVICE_URL}") - print(f" Timeout: {PRINT_SERVICE_TIMEOUT}s") - - return health_ok - -if __name__ == "__main__": - test_print_service_connection() \ No newline at end of file diff --git a/recticel_print_service/INSTALLATION_GUIDE.md b/recticel_print_service/INSTALLATION_GUIDE.md deleted file mode 100644 index 1eaa4a2..0000000 --- a/recticel_print_service/INSTALLATION_GUIDE.md +++ /dev/null @@ -1,146 +0,0 @@ -# Recticel Direct Print Service - Installation Guide - -## 🎯 Overview - -This service enables direct printing from web browsers to thermal label printers (Epson TM-T20, Citizen CTS-310, etc.) without requiring PDF generation or manual printer dialogs. - -## 🔧 Installation Steps - -### 1. **Build the C# Application** - -**Requirements:** -- Visual Studio 2019 or later -- .NET Framework 4.7.2 or later -- Windows 10/11 - -**Build Steps:** -1. Open `RecticelPrintService.sln` in Visual Studio -2. Restore NuGet packages (Newtonsoft.Json) -3. Build in Release mode -4. Copy the entire `bin\Release` folder to `C:\RecticelPrintService\` - -### 2. **Register the Custom Protocol** - -**Option A: Double-click the registry file** -1. Right-click `recticel-print-protocol.reg` -2. Select "Run as administrator" -3. Confirm the registry import - -**Option B: Manual registry import** -1. Open Command Prompt as Administrator -2. Run: `reg import "recticel-print-protocol.reg"` - -### 3. **Install Printer Drivers** - -**For Epson TM-T20:** -- Download and install Epson TM-T20 drivers from Epson website -- Configure printer as "Epson TM-T20" in Windows - -**For Citizen CTS-310:** -- Download and install Citizen CTS-310 drivers -- Configure printer as "Citizen CTS-310" in Windows - -### 4. **Configure Printer Settings** - -1. Open Windows "Printers & scanners" -2. Set paper size to **80mm x 110mm** (or closest available) -3. Set print quality to **300 DPI** for thermal printers -4. Disable margins (set to 0 if possible) - -### 5. **Test the Installation** - -1. Open your web browser -2. Navigate to the print module page -3. Select an order -4. Choose "Direct Print" option -5. Select your thermal printer -6. Click "Print Labels" - -## 🖨️ Printer Configuration - -### Label Size Settings -- **Width**: 80mm -- **Height**: 110mm -- **Margins**: 0mm (all sides) -- **Print Quality**: 300 DPI - -### Thermal Printer Specific Settings - -**Epson TM-T20:** -- Paper Type: Continuous label -- Print Speed: Normal -- Print Density: Adjust based on label stock - -**Citizen CTS-310:** -- Media Type: Label -- Print Method: Thermal Transfer or Direct Thermal -- Print Speed: Medium - -## 🔄 How It Works - -1. **Web Interface**: User selects order and clicks "Direct Print" -2. **Data Encoding**: Order data is encoded as Base64 JSON -3. **Custom Protocol**: Browser calls `recticel-print://printer/data` -4. **Service Activation**: Windows launches RecticelPrintService.exe -5. **Data Processing**: Service decodes and formats label data -6. **Direct Printing**: Label is sent directly to the thermal printer -7. **Status Update**: Database is updated to mark order as printed - -## 🚀 URL Format - -``` -recticel-print://[printer_name]/[base64_encoded_json] -``` - -**Example:** -``` -recticel-print://Epson%20TM-T20/eyJvcmRlcl9pZCI6MTIzLCJjb21hbmRhX3Byb2R1Y3RpZSI6IkNQMDAwMDA3MTEifQ== -``` - -## ⚠️ Troubleshooting - -### Service Not Starting -1. Check if the service is installed in `C:\RecticelPrintService\` -2. Verify registry entries are correct -3. Run as Administrator if needed - -### Printer Not Found -1. Check printer name in Windows exactly matches selection -2. Ensure printer drivers are installed -3. Test print from Windows to verify printer works - -### Labels Not Printing -1. Verify paper size is set to 80x110mm -2. Check printer margins are set to 0 -3. Ensure thermal paper is loaded correctly - -### Browser Security -- Some browsers may block custom protocols -- Add site to trusted sites if needed -- Chrome may show a confirmation dialog - -## 🔧 Advanced Configuration - -### Custom Printer Names -Users can add custom printer names by selecting "Other Printer..." and entering the exact Windows printer name. - -### Multiple Label Quantities -The service automatically prints the quantity specified in the order, with sequential numbering (CP00000711-001, CP00000711-002, etc.). - -### Fallback to PDF -If direct printing fails, users can switch to "Generate PDF" mode for manual printing. - -## 📞 Support - -For technical support: -1. Check Windows Event Viewer for service errors -2. Verify printer connectivity and driver installation -3. Test with PDF generation mode as fallback -4. Contact IT support with specific error messages - -## 🔒 Security Notes - -- The service only processes label data from trusted sources -- Registry changes require Administrator privileges -- Service runs with current user permissions -- No network connections are made by the service \ No newline at end of file diff --git a/recticel_print_service/RecticelPrintService.sln b/recticel_print_service/RecticelPrintService.sln deleted file mode 100644 index 8b086dd..0000000 --- a/recticel_print_service/RecticelPrintService.sln +++ /dev/null @@ -1,24 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28010.2046 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RecticelPrintService", "RecticelPrintService\RecticelPrintService.csproj", "{41ED6235-3C76-4723-A5F6-02D2FA51E677}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {41ED6235-3C76-4723-A5F6-02D2FA51E677}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {41ED6235-3C76-4723-A5F6-02D2FA51E677}.Debug|Any CPU.Build.0 = Debug|Any CPU - {41ED6235-3C76-4723-A5F6-02D2FA51E677}.Release|Any CPU.ActiveCfg = Release|Any CPU - {41ED6235-3C76-4723-A5F6-02D2FA51E677}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {FC401D2A-E68E-47EE-B315-E1A2F0B292FA} - EndGlobalSection -EndGlobal \ No newline at end of file diff --git a/recticel_print_service/RecticelPrintService/App.config b/recticel_print_service/RecticelPrintService/App.config deleted file mode 100644 index a021ad2..0000000 --- a/recticel_print_service/RecticelPrintService/App.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/recticel_print_service/RecticelPrintService/LabelPrinter.cs b/recticel_print_service/RecticelPrintService/LabelPrinter.cs deleted file mode 100644 index d176451..0000000 --- a/recticel_print_service/RecticelPrintService/LabelPrinter.cs +++ /dev/null @@ -1,288 +0,0 @@ -using System; -using System.Drawing; -using System.Drawing.Printing; -using System.Text; -using Newtonsoft.Json; - -namespace RecticelPrintService -{ - public class LabelPrinter - { - private PrintData _labelData; - - // Label dimensions in millimeters (80x110mm) - private const float LABEL_WIDTH_MM = 80f; - private const float LABEL_HEIGHT_MM = 110f; - - // Convert mm to hundredths of an inch (used by .NET printing) - private float MmToHundredthsOfInch(float mm) - { - return mm * 3.937f; // 1mm = 0.03937 inches, * 100 for hundredths - } - - public bool PrintLabel(string printerName, string jsonData) - { - try - { - // Parse JSON data - _labelData = JsonConvert.DeserializeObject(jsonData); - - if (_labelData == null) - { - Console.WriteLine("Failed to parse JSON data"); - return false; - } - - // Set up print document - PrintDocument printDoc = new PrintDocument(); - printDoc.PrinterSettings.PrinterName = printerName; - - // Check if printer exists - if (!printDoc.PrinterSettings.IsValid) - { - Console.WriteLine($"Printer '{printerName}' not found or not available"); - Console.WriteLine("Available printers:"); - foreach (string printer in PrinterSettings.InstalledPrinters) - { - Console.WriteLine($" - {printer}"); - } - return false; - } - - // Set paper size for 80x110mm labels - PaperSize labelSize = new PaperSize("Label 80x110mm", - (int)MmToHundredthsOfInch(LABEL_WIDTH_MM), - (int)MmToHundredthsOfInch(LABEL_HEIGHT_MM)); - - printDoc.DefaultPageSettings.PaperSize = labelSize; - printDoc.DefaultPageSettings.Margins = new Margins(0, 0, 0, 0); - - // Set print event handler - printDoc.PrintPage += PrintDoc_PrintPage; - - // Print the document - printDoc.Print(); - - return true; - } - catch (Exception ex) - { - Console.WriteLine($"Error printing label: {ex.Message}"); - return false; - } - } - - private void PrintDoc_PrintPage(object sender, PrintPageEventArgs e) - { - try - { - Graphics g = e.Graphics; - - // Define fonts - Font companyFont = new Font("Arial", 10, FontStyle.Bold); - Font headerFont = new Font("Arial", 8, FontStyle.Bold); - Font dataFont = new Font("Arial", 9, FontStyle.Bold); - Font labelFont = new Font("Arial", 7); - Font barcodeFont = new Font("Courier New", 6, FontStyle.Bold); - - // Define brushes and pens - Brush textBrush = Brushes.Black; - Pen borderPen = new Pen(Color.Black, 2); - Pen dividerPen = new Pen(Color.Gray, 1); - - // Calculate positions (in pixels, 300 DPI assumed) - float dpiX = e.Graphics.DpiX; - float dpiY = e.Graphics.DpiY; - - // Convert mm to pixels - float labelWidth = (LABEL_WIDTH_MM / 25.4f) * dpiX; - float labelHeight = (LABEL_HEIGHT_MM / 25.4f) * dpiY; - - // Content area (similar to your HTML preview) - float contentX = (3f / 25.4f) * dpiX; // 3mm margin - float contentY = (15f / 25.4f) * dpiY; // 15mm from bottom - float contentWidth = (60f / 25.4f) * dpiX; // 60mm width - float contentHeight = (85f / 25.4f) * dpiY; // 85mm height - - // Draw main content border - g.DrawRectangle(borderPen, contentX, contentY, contentWidth, contentHeight); - - // Calculate row height - float rowHeight = contentHeight / 10f; // 9 rows + spacing - float currentY = contentY; - - // Row 1: Company Header - string companyText = "INNOFA RROMANIA SRL"; - SizeF companySize = g.MeasureString(companyText, companyFont); - float companyX = contentX + (contentWidth - companySize.Width) / 2; - g.DrawString(companyText, companyFont, textBrush, companyX, currentY + rowHeight/3); - currentY += rowHeight; - - // Horizontal divider after company - g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); - - // Row 2: Customer Name - string customerName = _labelData.CustomerName ?? "N/A"; - SizeF customerSize = g.MeasureString(customerName, headerFont); - float customerX = contentX + (contentWidth - customerSize.Width) / 2; - g.DrawString(customerName, headerFont, textBrush, customerX, currentY + rowHeight/3); - currentY += rowHeight; - - // Horizontal divider after customer - g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); - - // Vertical divider (40% from left) - float verticalDividerX = contentX + contentWidth * 0.4f; - g.DrawLine(dividerPen, verticalDividerX, currentY, verticalDividerX, contentY + contentHeight); - - // Row 3: Quantity - g.DrawString("Quantity ordered", labelFont, textBrush, contentX + 5, currentY + rowHeight/4); - string quantity = _labelData.Cantitate.ToString(); - SizeF qtySize = g.MeasureString(quantity, dataFont); - float qtyX = verticalDividerX + (contentWidth * 0.6f - qtySize.Width) / 2; - g.DrawString(quantity, dataFont, textBrush, qtyX, currentY + rowHeight/4); - currentY += rowHeight; - - // Horizontal divider - g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); - - // Row 4: Customer Order - g.DrawString("Customer order", labelFont, textBrush, contentX + 5, currentY + rowHeight/4); - string customerOrder = $"{_labelData.ComAchizClient}-{_labelData.NrLinieComClient}"; - if (string.IsNullOrEmpty(_labelData.ComAchizClient)) customerOrder = "N/A"; - SizeF orderSize = g.MeasureString(customerOrder, dataFont); - float orderX = verticalDividerX + (contentWidth * 0.6f - orderSize.Width) / 2; - g.DrawString(customerOrder, dataFont, textBrush, orderX, currentY + rowHeight/4); - currentY += rowHeight; - - // Horizontal divider - g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); - - // Row 5: Delivery Date - g.DrawString("Delivery date", labelFont, textBrush, contentX + 5, currentY + rowHeight/4); - string deliveryDate = _labelData.DataLivrare ?? "N/A"; - if (!string.IsNullOrEmpty(deliveryDate) && deliveryDate != "N/A") - { - try - { - DateTime dt = DateTime.Parse(deliveryDate); - deliveryDate = dt.ToString("dd/MM/yyyy"); - } - catch { } - } - SizeF dateSize = g.MeasureString(deliveryDate, dataFont); - float dateX = verticalDividerX + (contentWidth * 0.6f - dateSize.Width) / 2; - g.DrawString(deliveryDate, dataFont, textBrush, dateX, currentY + rowHeight/4); - currentY += rowHeight; - - // Horizontal divider - g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); - - // Row 6: Description (double height) - g.DrawString("Description", labelFont, textBrush, contentX + 5, currentY + rowHeight/4); - string description = _labelData.DescrComProd ?? "N/A"; - // Word wrap description if needed - RectangleF descRect = new RectangleF(verticalDividerX + 5, currentY + 5, - contentWidth * 0.6f - 10, rowHeight * 2 - 10); - g.DrawString(description, dataFont, textBrush, descRect); - currentY += rowHeight * 2; - - // Horizontal divider - g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); - - // Row 7: Size - g.DrawString("Size", labelFont, textBrush, contentX + 5, currentY + rowHeight/4); - string size = _labelData.Dimensiune ?? "N/A"; - SizeF sizeSize = g.MeasureString(size, dataFont); - float sizeX = verticalDividerX + (contentWidth * 0.6f - sizeSize.Width) / 2; - g.DrawString(size, dataFont, textBrush, sizeX, currentY + rowHeight/4); - currentY += rowHeight; - - // Horizontal divider - g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); - - // Row 8: Article Code - g.DrawString("Article Code", labelFont, textBrush, contentX + 5, currentY + rowHeight/4); - string articleCode = _labelData.CustomerArticleNumber ?? "N/A"; - SizeF artSize = g.MeasureString(articleCode, dataFont); - float artX = verticalDividerX + (contentWidth * 0.6f - artSize.Width) / 2; - g.DrawString(articleCode, dataFont, textBrush, artX, currentY + rowHeight/4); - currentY += rowHeight; - - // Horizontal divider - g.DrawLine(dividerPen, contentX, currentY, contentX + contentWidth, currentY); - - // Row 9: Prod Order - g.DrawString("Prod Order", labelFont, textBrush, contentX + 5, currentY + rowHeight/4); - string prodOrder = _labelData.SequentialNumber ?? $"{_labelData.ComandaProductie}-{_labelData.Cantitate}"; - SizeF prodSize = g.MeasureString(prodOrder, dataFont); - float prodX = verticalDividerX + (contentWidth * 0.6f - prodSize.Width) / 2; - g.DrawString(prodOrder, dataFont, textBrush, prodX, currentY + rowHeight/4); - - // Bottom barcode area - float barcodeY = contentY + contentHeight + (5f / 25.4f) * dpiY; // 5mm below content - float barcodeWidth = contentWidth; - float barcodeHeight = (10f / 25.4f) * dpiY; // 10mm height - - // Draw barcode representation (simple lines) - DrawSimpleBarcode(g, contentX, barcodeY, barcodeWidth, barcodeHeight, prodOrder); - - // Barcode text - SizeF barcodeTextSize = g.MeasureString(prodOrder, barcodeFont); - float barcodeTextX = contentX + (contentWidth - barcodeTextSize.Width) / 2; - g.DrawString(prodOrder, barcodeFont, textBrush, barcodeTextX, barcodeY + barcodeHeight + 5); - - // Vertical barcode on the right side - float verticalBarcodeX = contentX + contentWidth + (5f / 25.4f) * dpiX; // 5mm to the right - float verticalBarcodeWidth = (8f / 25.4f) * dpiX; // 8mm width - DrawSimpleVerticalBarcode(g, verticalBarcodeX, contentY + rowHeight * 2, - verticalBarcodeWidth, contentHeight - rowHeight * 2, customerOrder); - - // Dispose resources - companyFont.Dispose(); - headerFont.Dispose(); - dataFont.Dispose(); - labelFont.Dispose(); - barcodeFont.Dispose(); - borderPen.Dispose(); - dividerPen.Dispose(); - } - catch (Exception ex) - { - Console.WriteLine($"Error in PrintPage event: {ex.Message}"); - } - } - - private void DrawSimpleBarcode(Graphics g, float x, float y, float width, float height, string data) - { - // Simple barcode representation using alternating lines - float barWidth = 2f; - bool drawBar = true; - - for (float currentX = x; currentX < x + width; currentX += barWidth) - { - if (drawBar) - { - g.FillRectangle(Brushes.Black, currentX, y, barWidth, height * 0.8f); - } - drawBar = !drawBar; - } - } - - private void DrawSimpleVerticalBarcode(Graphics g, float x, float y, float width, float height, string data) - { - // Simple vertical barcode representation - float barHeight = 2f; - bool drawBar = true; - - for (float currentY = y; currentY < y + height; currentY += barHeight) - { - if (drawBar) - { - g.FillRectangle(Brushes.Black, x, currentY, width * 0.8f, barHeight); - } - drawBar = !drawBar; - } - } - } -} \ No newline at end of file diff --git a/recticel_print_service/RecticelPrintService/PrintData.cs b/recticel_print_service/RecticelPrintService/PrintData.cs deleted file mode 100644 index 8036369..0000000 --- a/recticel_print_service/RecticelPrintService/PrintData.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Newtonsoft.Json; - -namespace RecticelPrintService -{ - public class PrintData - { - [JsonProperty("order_id")] - public int OrderId { get; set; } - - [JsonProperty("comanda_productie")] - public string ComandaProductie { get; set; } - - [JsonProperty("customer_name")] - public string CustomerName { get; set; } - - [JsonProperty("cantitate")] - public int Cantitate { get; set; } - - [JsonProperty("com_achiz_client")] - public string ComAchizClient { get; set; } - - [JsonProperty("nr_linie_com_client")] - public string NrLinieComClient { get; set; } - - [JsonProperty("data_livrare")] - public string DataLivrare { get; set; } - - [JsonProperty("dimensiune")] - public string Dimensiune { get; set; } - - [JsonProperty("descr_com_prod")] - public string DescrComProd { get; set; } - - [JsonProperty("customer_article_number")] - public string CustomerArticleNumber { get; set; } - - [JsonProperty("cod_articol")] - public string CodArticol { get; set; } - - [JsonProperty("sequential_number")] - public string SequentialNumber { get; set; } - - [JsonProperty("current_label")] - public int CurrentLabel { get; set; } - - [JsonProperty("total_labels")] - public int TotalLabels { get; set; } - } -} \ No newline at end of file diff --git a/recticel_print_service/RecticelPrintService/Program.cs b/recticel_print_service/RecticelPrintService/Program.cs deleted file mode 100644 index a60f278..0000000 --- a/recticel_print_service/RecticelPrintService/Program.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Web; - -namespace RecticelPrintService -{ - class Program - { - static void Main(string[] args) - { - try - { - if (args.Length == 0) - { - Console.WriteLine("Recticel Print Service - No arguments provided"); - Console.WriteLine("Usage: RecticelPrintService.exe \"recticel-print://printer/data\""); - Console.ReadKey(); - return; - } - - string url = args[0]; - Console.WriteLine($"Received print request: {url}"); - - // Parse the custom protocol URL - // Format: recticel-print://printer_name/base64_encoded_json_data - if (!url.StartsWith("recticel-print://")) - { - Console.WriteLine("Invalid protocol. Expected: recticel-print://"); - Console.ReadKey(); - return; - } - - // Remove protocol prefix - string data = url.Substring("recticel-print://".Length); - - // Split printer name and data - string[] parts = data.Split('/'); - if (parts.Length < 2) - { - Console.WriteLine("Invalid URL format. Expected: recticel-print://printer_name/data"); - Console.ReadKey(); - return; - } - - string printerName = HttpUtility.UrlDecode(parts[0]); - string encodedData = HttpUtility.UrlDecode(parts[1]); - - Console.WriteLine($"Target Printer: {printerName}"); - Console.WriteLine($"Data Length: {encodedData.Length}"); - - // Decode base64 JSON data - byte[] dataBytes = Convert.FromBase64String(encodedData); - string jsonData = System.Text.Encoding.UTF8.GetString(dataBytes); - - Console.WriteLine($"Decoded JSON: {jsonData}"); - - // Parse and print the label - var printer = new LabelPrinter(); - bool success = printer.PrintLabel(printerName, jsonData); - - if (success) - { - Console.WriteLine("✅ Label printed successfully!"); - } - else - { - Console.WriteLine("❌ Failed to print label!"); - } - - // Keep console open for debugging (remove in production) - Console.WriteLine("Press any key to exit..."); - Console.ReadKey(); - } - catch (Exception ex) - { - Console.WriteLine($"Error: {ex.Message}"); - Console.WriteLine(ex.StackTrace); - Console.ReadKey(); - } - } - } -} \ No newline at end of file diff --git a/recticel_print_service/RecticelPrintService/Properties/AssemblyInfo.cs b/recticel_print_service/RecticelPrintService/Properties/AssemblyInfo.cs deleted file mode 100644 index e8a8bb7..0000000 --- a/recticel_print_service/RecticelPrintService/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("RecticelPrintService")] -[assembly: AssemblyDescription("Direct label printing service for Recticel Quality System")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Recticel")] -[assembly: AssemblyProduct("Recticel Print Service")] -[assembly: AssemblyCopyright("Copyright © Recticel 2025")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: Guid("41ed6235-3c76-4723-a5f6-02d2fa51e677")] - -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/recticel_print_service/RecticelPrintService/RecticelPrintService.csproj b/recticel_print_service/RecticelPrintService/RecticelPrintService.csproj deleted file mode 100644 index e82abac..0000000 --- a/recticel_print_service/RecticelPrintService/RecticelPrintService.csproj +++ /dev/null @@ -1,62 +0,0 @@ - - - - - Debug - AnyCPU - {41ED6235-3C76-4723-A5F6-02D2FA51E677} - Exe - RecticelPrintService - RecticelPrintService - v4.7.2 - 512 - true - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll - - - - - - - - - - - - - - \ No newline at end of file diff --git a/recticel_print_service/RecticelPrintService/packages.config b/recticel_print_service/RecticelPrintService/packages.config deleted file mode 100644 index a70468f..0000000 --- a/recticel_print_service/RecticelPrintService/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/recticel_print_service/install.bat b/recticel_print_service/install.bat deleted file mode 100644 index f55faa0..0000000 --- a/recticel_print_service/install.bat +++ /dev/null @@ -1,50 +0,0 @@ -@echo off -echo Installing Recticel Print Service... -echo. - -REM Check if running as Administrator -net session >nul 2>&1 -if %errorlevel% neq 0 ( - echo ERROR: This script must be run as Administrator. - echo Right-click and select "Run as administrator" - pause - exit /b 1 -) - -REM Create installation directory -echo Creating installation directory... -if not exist "C:\RecticelPrintService" ( - mkdir "C:\RecticelPrintService" -) - -REM Copy files (assuming this script is in the same directory as the built application) -echo Copying application files... -copy "RecticelPrintService\bin\Release\*.*" "C:\RecticelPrintService\" /Y - -REM Register custom protocol -echo Registering custom protocol... -reg import "recticel-print-protocol.reg" - -if %errorlevel% equ 0 ( - echo. - echo ✅ Installation completed successfully! - echo. - echo Service installed to: C:\RecticelPrintService\ - echo Protocol registered: recticel-print:// - echo. - echo Next steps: - echo 1. Configure your thermal label printer in Windows - echo 2. Set label size to 80mm x 110mm - echo 3. Test printing from the web interface - echo. - echo Press any key to exit... - pause >nul -) else ( - echo. - echo ❌ Installation failed! - echo Please check if you're running as Administrator. - echo. - pause -) - -exit /b 0 \ No newline at end of file diff --git a/recticel_print_service/recticel-print-protocol.reg b/recticel_print_service/recticel-print-protocol.reg deleted file mode 100644 index ea2a8ff..0000000 --- a/recticel_print_service/recticel-print-protocol.reg +++ /dev/null @@ -1,14 +0,0 @@ -Windows Registry Editor Version 5.00 - -[HKEY_CLASSES_ROOT\recticel-print] -@="URL:Recticel Print Protocol" -"URL Protocol"="" -"EditFlags"=dword:00000002 - -[HKEY_CLASSES_ROOT\recticel-print\shell] -@="open" - -[HKEY_CLASSES_ROOT\recticel-print\shell\open] - -[HKEY_CLASSES_ROOT\recticel-print\shell\open\command] -@="\"C:\\RecticelPrintService\\RecticelPrintService.exe\" \"%1\"" \ No newline at end of file diff --git a/windows_print_service/ERROR_1053_COMPLETE_FIX.md b/windows_print_service/ERROR_1053_COMPLETE_FIX.md deleted file mode 100644 index 03ce2a4..0000000 --- a/windows_print_service/ERROR_1053_COMPLETE_FIX.md +++ /dev/null @@ -1,224 +0,0 @@ -# Windows Service Error 1053 - COMPLETE FIX PACKAGE - -## 🎯 Problem Description - -**Windows Service Error 1053**: "The service did not respond to the start or control request in a timely fashion." - -This error occurs when: -- Service takes too long to respond to Windows Service Control Manager (SCM) -- Python process doesn't communicate properly with Windows services -- Service wrapper doesn't handle SCM signals correctly -- Dependencies or paths are incorrect - -## 📦 Complete Solution Package - -This package provides **4 different installation methods** and comprehensive Error 1053 fixes: - -### 🔧 Installation Files - -1. **`install_service_ENHANCED.bat`** - Main installer with multiple fallback methods -2. **`fix_error_1053.bat`** - Dedicated Error 1053 diagnostic and fix tool -3. **`print_service_complete.py`** - Enhanced service with proper Windows service support -4. **`service_wrapper.py`** - Optional advanced service wrapper -5. **`test_service.bat`** - Standalone testing tool - -### 🚀 Installation Methods (Automatic Fallback) - -#### Method 1: Windows SC Service (Preferred) -- Creates standard Windows service -- Includes enhanced timeout handling -- Automatic recovery configuration -- **Fixes Error 1053** with proper SCM communication - -#### Method 2: Task Scheduler Service (Fallback) -- Runs as scheduled task on system startup -- SYSTEM privileges with highest elevation -- Automatic restart on failure -- Bypasses SCM timeout issues - -#### Method 3: Startup Script (Manual Fallback) -- Runs from Windows startup folder -- Simple and reliable -- Manual process management -- Always works as final resort - -#### Method 4: Standalone Mode (Testing/Debugging) -- Direct Python execution -- No Windows service wrapper -- Immediate startup for testing -- Perfect for troubleshooting - -## 🔍 Error 1053 Specific Fixes - -### Root Cause Analysis -The enhanced installers address these Error 1053 causes: - -1. **SCM Timeout Issues** - - Enhanced service wrapper responds immediately to SCM - - Service process starts in background - - Proper exit codes and signaling - -2. **Python Path Problems** - - Automatic detection of embedded Python - - Fallback to system Python - - Absolute path resolution - -3. **Service Communication** - - Proper Windows service signal handling - - Enhanced logging and error reporting - - Background process management - -4. **Dependency Issues** - - Self-contained Python environment - - Zero external dependencies - - Embedded Python distribution included - -### Technical Implementation - -#### Enhanced Service Wrapper -```batch -# error_1053_fix_wrapper.bat -- Immediate SCM response -- Background service startup -- Enhanced error handling -- Comprehensive logging -``` - -#### Service Configuration -```cmd -# Delayed auto-start to prevent startup conflicts -sc config QualityPrintService start= delayed-auto - -# Automatic recovery on failure -sc failure QualityPrintService reset= 86400 actions= restart/5000/restart/5000/restart/5000 -``` - -## 📋 Usage Instructions - -### 🎯 Quick Fix (Recommended) -1. **Run as Administrator**: `fix_error_1053.bat` -2. This script will: - - Diagnose the current problem - - Apply all Error 1053 fixes - - Test service functionality - - Install with enhanced wrapper - -### 🔧 Fresh Installation -1. **Run as Administrator**: `install_service_ENHANCED.bat` -2. Installer will automatically: - - Try Windows SC Service first - - Fall back to Task Scheduler if needed - - Create startup script as final option - - Test all methods until one succeeds - -### 🧪 Testing and Verification -1. **Test standalone**: `test_service.bat` -2. **Manual testing**: - ```cmd - cd C:\QualityPrintService - python print_service_complete.py --test - python print_service_complete.py --standalone - ``` -3. **Service status**: - ```cmd - sc query QualityPrintService - net start QualityPrintService - ``` - -## 🔍 Troubleshooting Guide - -### If Error 1053 Still Occurs - -1. **Run Diagnostic Tool**: - ```cmd - fix_error_1053.bat - ``` - -2. **Check Logs**: - - `%USERPROFILE%\PrintService\logs\service_wrapper.log` - - `%USERPROFILE%\PrintService\logs\error_1053_fix.log` - -3. **Manual Service Test**: - ```cmd - C:\QualityPrintService\error_1053_fix_wrapper.bat - ``` - -4. **Alternative Installation**: - - Use Task Scheduler method - - Use Startup Script method - - Run in standalone mode - -### Common Issues and Solutions - -| Issue | Solution | -|-------|----------| -| "Python not found" | Use embedded Python package or install Python 3.7+ | -| "Port 8765 in use" | Stop existing services, reboot system | -| "Access denied" | Run installer as Administrator | -| "Service won't start" | Use Task Scheduler fallback method | -| "Still Error 1053" | Use startup script or standalone mode | - -## ✅ Success Verification - -After installation, verify success: - -1. **Service Status**: Service should be "RUNNING" - ```cmd - sc query QualityPrintService - ``` - -2. **Network Test**: Should return "OK" - ```cmd - curl http://localhost:8765/health - ``` - -3. **Browser Test**: Open `http://localhost:8765/health` - -4. **Chrome Extension**: Should connect successfully - -## 📊 Package Contents Summary - -### Core Service Files -- ✅ `print_service_complete.py` - Main service with Windows service support -- ✅ `service_wrapper.py` - Advanced service wrapper (optional) -- ✅ Enhanced service wrappers with Error 1053 fixes - -### Installation Tools -- ✅ `install_service_ENHANCED.bat` - Multi-method installer -- ✅ `fix_error_1053.bat` - Dedicated Error 1053 fixer -- ✅ `test_service.bat` - Standalone testing tool - -### Zero Dependencies -- ✅ `python_embedded/` - Complete Python 3.11.9 distribution -- ✅ No external dependencies required -- ✅ Self-contained package (10.8MB) - -### Browser Integration -- ✅ `chrome_extension/` - Complete Chrome extension -- ✅ Automatic printer detection -- ✅ PDF processing and printing - -## 🎯 Expected Results - -After running the enhanced installer: - -✅ **Windows Service Error 1053 RESOLVED** -✅ **Service starts automatically on boot** -✅ **Multiple installation methods available** -✅ **Comprehensive error handling and recovery** -✅ **Zero external dependencies** -✅ **Complete diagnostic and troubleshooting tools** - -## 🚀 Next Steps - -1. **Install**: Run `install_service_ENHANCED.bat` as Administrator -2. **Verify**: Check service status and network connectivity -3. **Configure**: Install Chrome extension from `chrome_extension/` -4. **Test**: Print labels from web application -5. **Monitor**: Check logs for any issues - -The enhanced package provides **4 installation methods** and **comprehensive Error 1053 fixes** to ensure reliable service operation on all Windows systems. - ---- - -**Support**: All installation methods include detailed logging and diagnostic information to troubleshoot any remaining issues. \ No newline at end of file diff --git a/windows_print_service/INSTALLATION_COMPLETE.md b/windows_print_service/INSTALLATION_COMPLETE.md deleted file mode 100644 index 56b425c..0000000 --- a/windows_print_service/INSTALLATION_COMPLETE.md +++ /dev/null @@ -1,273 +0,0 @@ -# Quality Print Service - Complete Installation Guide - -## 🎯 Pre-Installation Checklist - -### System Requirements Verification: -- [ ] Windows 10 build 1903+ or Windows Server 2016+ -- [ ] Administrator access to the system -- [ ] Google Chrome browser installed -- [ ] At least 100 MB free disk space -- [ ] Network/USB printer connected and configured - -### Python Requirements: -- [ ] Python 3.7+ installed OR use included portable Python -- [ ] Python accessible via command line (optional) - -## 📦 Installation Methods - -### Method 1: Complete Automatic Installation (Recommended) - -1. **Download and Extract**: - - Extract the complete package to any folder (e.g., Desktop) - - No need to keep the files permanently - -2. **Run Installer**: - ``` - Right-click: install_service_complete.bat - Select: "Run as administrator" - ``` - -3. **Follow Installation Steps**: - ``` - [1/6] Administrator privileges confirmed ✓ - [2/6] Checking Python installation... - [3/6] Creating installation directories... - [4/6] Installing service files... - [5/6] Installing Windows service... - [6/6] Starting service... - ``` - -4. **Install Chrome Extension**: - - Chrome will open the extension folder automatically - - Go to `chrome://extensions/` - - Enable "Developer mode" (top right) - - Click "Load unpacked" - - Select the `chrome_extension` folder - -5. **Verify Installation**: - - Visit: `http://localhost:8765/health` - - Expected response: `{"status": "healthy"}` - -### Method 2: Manual Installation - -1. **Create Directories**: - ```cmd - mkdir C:\QualityPrintService - mkdir %USERPROFILE%\PrintService\logs - ``` - -2. **Copy Files**: - ```cmd - copy print_service_complete.py C:\QualityPrintService ``` - -3. **Install Service**: - ```cmd - sc create QualityPrintService binPath="python C:\QualityPrintService\print_service_complete.py" - sc start QualityPrintService - ``` - -## 🔧 Post-Installation Configuration - -### Service Verification: -```cmd -# Check service status -sc query QualityPrintService - -# Check service configuration -sc qc QualityPrintService - -# View service logs (if using NSSM) -type "%USERPROFILE%\PrintService\logs\service_output.log" -``` - -### Network Testing: -```powershell -# Test health endpoint -Invoke-RestMethod -Uri http://localhost:8765/health - -# Test printer endpoint -Invoke-RestMethod -Uri http://localhost:8765/printers - -# Test from browser -start http://localhost:8765/status -``` - -### Chrome Extension Setup: -1. Open Chrome browser -2. Navigate to `chrome://extensions/` -3. Enable "Developer mode" toggle (top-right corner) -4. Click "Load unpacked" button -5. Browse and select the `chrome_extension` folder -6. Verify extension appears in the list with green toggle - -## 🔍 Installation Verification - -### Health Check Procedure: -1. **Service Status**: Verify Windows service is running - ```cmd - sc query QualityPrintService | find "RUNNING" - ``` - -2. **Network Connectivity**: Test HTTP endpoints - ```cmd - curl http://localhost:8765/health - ``` - -3. **Printer Detection**: Check printer enumeration - ```cmd - curl http://localhost:8765/printers - ``` - -4. **Extension Communication**: Test from web page - - Open the Quality app in Chrome - - Go to print module - - Verify "Extension ready" status - -### Expected Responses: - -**Health Check**: -```json -{ - "status": "healthy", - "service": "Windows Print Service", - "version": "1.0.0", - "timestamp": "2025-09-25T10:30:00" -} -``` - -**Printer List**: -```json -{ - "success": true, - "printers": [ - {"name": "HP LaserJet", "type": "Local", "status": "Available"} - ], - "count": 1 -} -``` - -## 🚨 Troubleshooting Common Issues - -### Issue: "Administrator privileges required" -**Solution**: -- Right-click installer file -- Select "Run as administrator" -- Confirm UAC prompt - -### Issue: "Python not found" -**Solutions**: -1. Install Python from python.org -2. Use included portable Python -3. Add Python to system PATH - -### Issue: "Service failed to start" -**Solutions**: -1. Check Windows Event Viewer: - - Windows Logs → Application - - Filter by source: "Service Control Manager" -2. Verify port 8765 is not in use: - ```cmd - netstat -an | find "8765" - ``` -3. Check service logs: - ```cmd - type "%USERPROFILE%\PrintService\logs\print_service_*.log" - ``` - -### Issue: "Chrome extension not working" -**Solutions**: -1. Reload extension in `chrome://extensions/` -2. Check extension permissions -3. Verify service is responding at `localhost:8765` -4. Clear browser cache and cookies - -### Issue: "PDF printing fails" -**Solutions**: -1. Install Adobe Reader or SumatraPDF -2. Check printer permissions -3. Verify PDF file accessibility -4. Test with different printer - -## 🔄 Maintenance and Updates - -### Regular Maintenance: -- **Log Cleanup**: Logs rotate automatically -- **Service Monitoring**: Check service status weekly -- **Chrome Extension**: Update when prompted - -### Manual Service Management: -```cmd -# Stop service -sc stop QualityPrintService - -# Start service -sc start QualityPrintService - -# Restart service -sc stop QualityPrintService && timeout /t 3 && sc start QualityPrintService - -# Change startup type -sc config QualityPrintService start= auto -``` - -### Log File Locations: -- Service logs: `%USERPROFILE%\PrintService\logs\` -- Windows Event Logs: Event Viewer → Windows Logs → Application -- Chrome Extension: Chrome DevTools → Console - -## 🔧 Advanced Configuration - -### Custom Port Configuration: -Edit `print_service_complete.py`: -```python -server_address = ('localhost', 8765) # Change 8765 to desired port -``` - -### Custom Install Directory: -Edit `install_service_complete.bat`: -```batch -set INSTALL_DIR=C:\CustomPath\PrintService -``` - -### Service Recovery Options: -```cmd -sc failure QualityPrintService reset= 86400 actions= restart/5000/restart/10000/restart/30000 -``` - -## 📋 Uninstallation - -### Complete Removal: -1. Run `uninstall_service_complete.bat` as Administrator -2. Remove Chrome extension manually -3. Optional: Delete log files - -### Manual Removal: -```cmd -# Stop and remove service -sc stop QualityPrintService -sc delete QualityPrintService - -# Remove files -rmdir /s /q C:\QualityPrintService -rmdir /s /q "%USERPROFILE%\PrintService" -``` - -## 📞 Getting Help - -### Before Contacting Support: -1. Check this installation guide -2. Review troubleshooting section -3. Check service logs for error messages -4. Test with simple printer (like Microsoft Print to PDF) - -### Information to Provide: -- Windows version (run `winver`) -- Python version (run `python --version`) -- Service status (run `sc query QualityPrintService`) -- Recent log entries -- Error messages or screenshots - ---- -**Installation Guide Version**: 1.0.0 -**Last Updated**: September 2025 -**Support**: Internal Quality System Team diff --git a/windows_print_service/PACKAGE_SUMMARY.md b/windows_print_service/PACKAGE_SUMMARY.md deleted file mode 100644 index 316e04c..0000000 --- a/windows_print_service/PACKAGE_SUMMARY.md +++ /dev/null @@ -1,193 +0,0 @@ -# Quality Windows Print Service - Complete Self-Contained Package Summary - -## 📦 Package Overview - -This is a **complete, self-contained Windows print service** with **zero external dependencies** that enables silent PDF printing from the Quality Label web application. - -## 🎯 Key Features - -### ✅ Zero Dependencies -- Uses **only Python standard library** (no external packages required) -- Works with **any Python 3.7+** installation (system or portable) -- No complicated setup or package management - -### ✅ Complete Windows Integration -- **Windows Service** with automatic startup -- **Service recovery** with auto-restart on failure -- **Professional logging** with daily rotation -- **Chrome extension** for seamless web integration - -### ✅ Multiple Printing Methods (Automatic Fallback) -1. **Adobe Reader** command line printing -2. **SumatraPDF** automation -3. **PowerShell** printing commands -4. **Microsoft Edge** integration -5. **Windows system default** application - -### ✅ Robust Architecture -``` -Quality Web App → Chrome Extension → Windows Service → Physical Printer - (localhost only) (port 8765) (any printer) -``` - -## 📁 Package Contents - -### Core Service Files: -- `print_service_complete.py` - Main service (19KB, pure Python) -- `install_service_complete.bat` - Complete installer with Python detection -- `uninstall_service_complete.bat` - Clean removal script -- `requirements_complete.txt` - Dependencies list (all standard library) - -### Chrome Extension: -- `chrome_extension/manifest.json` - Extension configuration -- `chrome_extension/background.js` - Windows service communication -- `chrome_extension/popup.html` - Extension interface -- `chrome_extension/popup.js` - Extension functionality - -### Documentation: -- `README_COMPLETE.md` - Comprehensive technical documentation -- `INSTALLATION_COMPLETE.md` - Step-by-step installation guide -- `PORTABLE_PYTHON_INSTRUCTIONS.txt` - Python distribution options - -### Build Tools: -- `build_package.py` - Package builder and documentation generator -- `build_executable.bat` - Optional standalone .exe builder - -## 🚀 Installation Process (5 Minutes) - -### Prerequisites: -- Windows 10/11 or Windows Server 2016+ -- Administrator privileges -- Google Chrome browser -- Python 3.7+ (system or portable) - -### Steps: -1. **Extract Package** - Extract ZIP to any temporary location -2. **Run Installer** - Right-click `install_service_complete.bat` → "Run as administrator" -3. **Install Extension** - Load `chrome_extension` folder in Chrome -4. **Test Service** - Visit http://localhost:8765/health - -## 🔧 Technical Specifications - -### Service Details: -- **Port**: 8765 (localhost only for security) -- **Memory Usage**: ~15-30 MB -- **CPU Usage**: <1% (idle) -- **Installation Path**: `C:\QualityPrintService\` -- **Logs**: `%USERPROFILE%\PrintService\logs\` - -### API Endpoints: -- `GET /health` - Service health check and status -- `GET /printers` - List available system printers -- `GET /status` - Service statistics and uptime -- `POST /print_pdf` - Print PDF file (supports page-by-page) - -### Printing Workflow: -1. User selects order in Quality web app -2. User clicks "Print Labels" -3. Chrome extension detects Windows service -4. PDF is generated and sent to service -5. Service downloads PDF and prints using best available method -6. Temporary files are automatically cleaned up - -## 🛡️ Security & Reliability - -### Security Features: -- **Localhost only** - Service only accepts connections from 127.0.0.1 -- **No external network** - All communication is local -- **Secure PDF handling** - Temporary files with auto-cleanup -- **Extension origin validation** - Chrome extension verifies sender origins - -### Reliability Features: -- **Service recovery** - Auto-restart on failure (3 attempts) -- **Multiple print methods** - Automatic fallback if one method fails -- **Error logging** - Comprehensive error tracking and debugging -- **Health monitoring** - Built-in health checks and status reporting - -## 📈 Advantages Over Previous Approaches - -### vs Chrome-Only Printing: -- ✅ **No browser security restrictions** -- ✅ **True silent printing** (no print dialogs) -- ✅ **Reliable printer selection** -- ✅ **Page-by-page printing support** - -### vs PowerShell-Only Service: -- ✅ **More portable** (works without PowerShell expertise) -- ✅ **Better error handling** and logging -- ✅ **More printing methods** available -- ✅ **Easier debugging** and maintenance - -### vs External Dependencies: -- ✅ **Zero package management** complexity -- ✅ **No version conflicts** or update issues -- ✅ **Works on restricted systems** -- ✅ **Smaller footprint** and faster startup - -## 🎯 Why This Solution Works - -### For IT Administrators: -- **Simple deployment** - One ZIP file, one installer command -- **Professional service** - Proper Windows service with logging -- **Easy maintenance** - Self-contained with automatic recovery -- **Security compliant** - Localhost only, no external dependencies - -### For End Users: -- **Transparent operation** - Just click print, labels appear -- **No manual steps** - No print dialogs or file management -- **Reliable printing** - Multiple fallback methods ensure success -- **Professional interface** - Clean integration with Quality app - -### For Developers: -- **Clean architecture** - Clear separation of concerns -- **Extensible design** - Easy to add new printing methods -- **Comprehensive logging** - Full debugging and monitoring -- **Standard protocols** - HTTP API for easy integration - -## 🔮 Future Enhancements - -### Planned Features: -- **Print queue management** - View and manage pending jobs -- **Printer status monitoring** - Real-time printer health checks -- **Print job history** - Track completed and failed jobs -- **Configuration GUI** - Windows app for service settings - -### Optional Add-ons: -- **Standalone .exe** - Single file deployment (using PyInstaller) -- **MSI installer** - Enterprise deployment package -- **Network printing** - Remote printer support -- **Print templates** - Custom label formats - -## 📊 Installation Statistics - -### Installation Time: **~5 minutes** -- Package extraction: 30 seconds -- Service installation: 2 minutes -- Chrome extension: 1 minute -- Testing and verification: 1.5 minutes - -### Maintenance Required: **Zero** -- Auto-starts with Windows -- Self-recovery on failure -- Automatic log rotation -- No user intervention needed - -## 🎉 Ready for Production - -This package is **production-ready** and includes: -- ✅ Complete installation automation -- ✅ Professional error handling -- ✅ Comprehensive documentation -- ✅ Testing and verification tools -- ✅ Clean uninstallation process - -**The Quality Windows Print Service provides enterprise-grade label printing with consumer-friendly simplicity.** - ---- -**Package Version**: 1.0.0 Complete -**Build Date**: September 25, 2025 -**Python Compatibility**: 3.7+ (all versions) -**Windows Compatibility**: Windows 10+ / Server 2016+ -**Chrome Compatibility**: All recent versions - -**Status**: ✅ Production Ready - Zero Dependencies - Self Contained \ No newline at end of file diff --git a/windows_print_service/PORTABLE_PYTHON_INSTRUCTIONS.txt b/windows_print_service/PORTABLE_PYTHON_INSTRUCTIONS.txt deleted file mode 100644 index ba2034d..0000000 --- a/windows_print_service/PORTABLE_PYTHON_INSTRUCTIONS.txt +++ /dev/null @@ -1,39 +0,0 @@ - -# PORTABLE PYTHON PACKAGE INSTRUCTIONS - -To create a complete self-contained package, you need to include a portable Python interpreter. - -## Option 1: Download Embedded Python (Recommended) -1. Download Python 3.11 Embedded from: https://www.python.org/downloads/windows/ -2. Choose "Windows embeddable package (64-bit)" or "(32-bit)" -3. Extract to a folder named 'python_portable' -4. The structure should be: - python_portable/ - ├── python.exe - ├── python311.dll (or similar) - ├── pythoncom311.dll - └── ... (other Python files) - -## Option 2: Use PyInstaller (Alternative) -1. Install PyInstaller: pip install pyinstaller -2. Run: pyinstaller --onefile --noconsole print_service_complete.py -3. This creates a single .exe file with all dependencies - -## Option 3: Manual Python Installation Check -The installer will check for system Python and use it if available. - -## Current Package Structure -This package includes: -✓ Complete Python script with all dependencies -✓ Windows service installer -✓ Chrome extension -✓ Logging and error handling -✓ Multiple printing method fallbacks -✓ Automatic recovery options - -## Dependencies Included in Python Script: -- All standard library modules (http.server, json, subprocess, etc.) -- No external dependencies required -- Pure Python implementation - -The service will work with any Python 3.7+ installation. diff --git a/windows_print_service/QualityPrintService_COMPLETE_ZERO_DEPENDENCIES.zip b/windows_print_service/QualityPrintService_COMPLETE_ZERO_DEPENDENCIES.zip deleted file mode 100644 index 376e4b9..0000000 Binary files a/windows_print_service/QualityPrintService_COMPLETE_ZERO_DEPENDENCIES.zip and /dev/null differ diff --git a/windows_print_service/README_COMPLETE.md b/windows_print_service/README_COMPLETE.md deleted file mode 100644 index eb5adf4..0000000 --- a/windows_print_service/README_COMPLETE.md +++ /dev/null @@ -1,167 +0,0 @@ -# Quality Windows Print Service - Complete Self-Contained Package - -## 🎯 Overview -This is a complete, self-contained Windows print service for Quality Label system with zero external dependencies. - -## 📦 Package Contents - -### Core Files: -- `print_service_complete.py` - Main Python service (uses only standard library) -- `install_service_complete.bat` - Complete installer (run as Administrator) -- `uninstall_service_complete.bat` - Complete uninstaller -- `requirements_complete.txt` - Dependencies list (all standard library) - -### Chrome Extension: -- `chrome_extension/` - Complete Chrome extension for web integration -- `chrome_extension/manifest.json` - Extension configuration -- `chrome_extension/background.js` - Service communication -- `chrome_extension/popup.html` - Extension interface - -### Documentation: -- `README.md` - This file -- `PORTABLE_PYTHON_INSTRUCTIONS.txt` - Guide for Python distribution -- `INSTALLATION_COMPLETE.md` - Detailed installation guide - -### Optional Build Tools: -- `build_executable.bat` - Creates standalone .exe (requires PyInstaller) -- `build_package.py` - Package builder script - -## 🚀 Quick Installation (5 Minutes) - -### Prerequisites: -- Windows 10/11 or Windows Server 2016+ -- Administrator privileges -- Python 3.7+ (or use included portable Python) -- Google Chrome browser - -### Steps: -1. **Extract Package**: Extract all files to a temporary location -2. **Run Installer**: Right-click `install_service_complete.bat` → "Run as administrator" -3. **Install Extension**: Load `chrome_extension` folder in Chrome (chrome://extensions/) -4. **Test Service**: Visit http://localhost:8765/health - -## 🔧 Technical Details - -### Service Architecture: -``` -Web App → Chrome Extension → Windows Service → Printer -``` - -### Features: -- ✅ Pure Python implementation (standard library only) -- ✅ Multiple printing methods (Adobe Reader, SumatraPDF, PowerShell, Edge, System Default) -- ✅ Automatic service recovery and restart -- ✅ Comprehensive logging system -- ✅ Cross-printer compatibility -- ✅ Zero external dependencies -- ✅ Windows service integration -- ✅ Chrome extension communication - -### Service Endpoints: -- `GET /health` - Service health check -- `GET /printers` - List available printers -- `GET /status` - Service status and statistics -- `POST /print_pdf` - Print PDF file - -### Printing Methods (Fallback Chain): -1. Adobe Reader command line -2. SumatraPDF automation -3. PowerShell printing -4. Microsoft Edge integration -5. System default application - -## 🛠️ Advanced Configuration - -### Service Configuration: -- Service Name: `QualityPrintService` -- Display Name: `Quality Label Print Service` -- Installation Path: `C:\QualityPrintService\` -- Log Directory: `%USERPROFILE%\PrintService\logs\` -- Port: `8765` (localhost only) - -### Logging: -- Daily log rotation -- Separate error and output logs -- Configurable log levels -- Automatic cleanup - -### Recovery Options: -- Auto-restart on failure (3 attempts) -- 5-second delay between restarts -- 24-hour reset period -- Scheduled task fallback - -## 🐛 Troubleshooting - -### Service Won't Start: -1. Check Windows Event Viewer -2. Verify Python installation -3. Check port 8765 availability -4. Run as Administrator - -### Printing Issues: -1. Verify printer installation -2. Check printer permissions -3. Test with different print methods -4. Review service logs - -### Extension Issues: -1. Reload extension in Chrome -2. Check extension permissions -3. Verify service connectivity -4. Clear browser cache - -### Common Solutions: -```bash -# Check service status -sc query QualityPrintService - -# Restart service -sc stop QualityPrintService -sc start QualityPrintService - -# Test connectivity -curl http://localhost:8765/health - -# View logs -type "%USERPROFILE%\PrintService\logs\print_service_*.log" -``` - -## 📋 System Requirements - -### Minimum Requirements: -- Windows 10 (1903) or Windows Server 2016 -- 50 MB free disk space -- Python 3.7+ (can be portable) -- Chrome/Edge browser -- Local printer access - -### Recommended: -- Windows 10/11 (latest) -- 100 MB free disk space -- Python 3.9+ -- Administrative privileges -- Network printer access - -## 🔒 Security Notes -- Service runs on localhost only (127.0.0.1:8765) -- No external network access required -- Uses Windows authentication -- Temporary files auto-cleanup -- Secure PDF handling - -## 🚀 Performance -- Memory usage: ~15-30 MB -- CPU usage: <1% (idle) -- Startup time: ~2 seconds -- Print processing: ~1-3 seconds per job - -## 📞 Support -For issues or questions: -1. Check this README -2. Review log files -3. Test with different browsers -4. Verify printer connectivity - -## 📝 License -Internal use only - Quality Label System diff --git a/windows_print_service/TROUBLESHOOTING_1053.md b/windows_print_service/TROUBLESHOOTING_1053.md deleted file mode 100644 index 717f6ae..0000000 --- a/windows_print_service/TROUBLESHOOTING_1053.md +++ /dev/null @@ -1,165 +0,0 @@ -# Windows Print Service - Error 1053 Troubleshooting Guide - -## 🚨 Windows Service Error 1053 - "Service did not respond to start or control request" - -This error occurs when Windows services don't communicate properly with the Service Control Manager (SCM). Here's how to fix it: - -### 🔧 SOLUTION 1: Use the Enhanced Service Package - -**Problem**: The original service wasn't designed for Windows service requirements. -**Fix**: Updated service architecture with proper Windows service communication. - -#### New Files Included: -- ✅ `service_wrapper.py` - Handles Windows service communication -- ✅ `print_service_complete.py` - Enhanced with signal handling and proper shutdown -- ✅ `test_service.bat` - Test service in standalone mode before installing - -### 🧪 STEP-BY-STEP TROUBLESHOOTING: - -#### Step 1: Test Service in Standalone Mode -```cmd -# Run this to test the service before installing as Windows service -test_service.bat -``` - -If this works, the service code is fine. If not, check the logs. - -#### Step 2: Check Python and Dependencies -```cmd -# Verify Python embedded is working -cd C:\QualityPrintService\python_embedded -python.exe --version - -# Test the service script directly -python.exe ..\print_service_complete.py --test -``` - -#### Step 3: Install with Enhanced Wrapper -The installer now creates a service wrapper that properly communicates with Windows SCM: - -```cmd -# Uninstall old service -sc stop QualityPrintService -sc delete QualityPrintService - -# Reinstall with enhanced wrapper -install_service_complete.bat -``` - -#### Step 4: Manual Service Control -```cmd -# Start service manually to see error details -net start QualityPrintService - -# Check service status -sc query QualityPrintService - -# View service logs -type "%USERPROFILE%\PrintService\logs\service_wrapper_*.log" -``` - -### 🔍 DIAGNOSTIC COMMANDS: - -#### Check Service Installation: -```cmd -sc query QualityPrintService -sc qc QualityPrintService -``` - -#### Check Port Availability: -```cmd -netstat -an | findstr :8765 -``` - -#### Test HTTP Endpoints: -```cmd -curl http://localhost:8765/health -# OR -powershell Invoke-WebRequest -Uri "http://localhost:8765/health" -``` - -### 📋 COMMON SOLUTIONS: - -#### Solution A: Port Already in Use -```cmd -# Find process using port 8765 -netstat -ano | findstr :8765 -# Kill process if needed (replace PID) -taskkill /PID /F -``` - -#### Solution B: Python Path Issues -```cmd -# Verify Python embedded path in service wrapper -type "C:\QualityPrintService\service_wrapper.bat" -``` - -#### Solution C: Permissions Issues -```cmd -# Run installer as Administrator -# Right-click install_service_complete.bat → "Run as administrator" -``` - -#### Solution D: Service Recovery -```cmd -# Configure automatic recovery -sc failure QualityPrintService reset= 86400 actions= restart/5000/restart/5000/restart/5000 -``` - -### 📊 SERVICE STATUS VERIFICATION: - -#### Successful Service Start: -- Service Status: RUNNING -- HTTP Response: `{"status": "healthy", "service": "Windows Print Service"}` -- Log Shows: "Service is ready and listening..." - -#### Failed Service Start: -- Service Status: STOPPED or START_PENDING -- HTTP Response: Connection refused -- Log Shows: Error messages with specific details - -### 🛠️ ADVANCED TROUBLESHOOTING: - -#### Enable Debug Logging: -Edit the service script to increase logging level: -```python -logging.basicConfig(level=logging.DEBUG) -``` - -#### Manual Service Wrapper Test: -```cmd -cd C:\QualityPrintService -python_embedded\python.exe service_wrapper.py -``` - -#### Windows Event Viewer: -1. Open Event Viewer -2. Navigate: Windows Logs → Application -3. Filter by Source: Service Control Manager -4. Look for QualityPrintService errors - -### 📞 SUPPORT CHECKLIST: - -Before reporting issues, please verify: - -- [ ] ✅ Python embedded is working (`python_embedded\python.exe --version`) -- [ ] ✅ Service runs in standalone mode (`test_service.bat`) -- [ ] ✅ Port 8765 is available (`netstat -an | findstr :8765`) -- [ ] ✅ Installer was run as Administrator -- [ ] ✅ Windows is Windows 10/11 or Server 2016+ -- [ ] ✅ Service logs show specific error messages - -### 🎯 EXPECTED RESULTS: - -After following this guide: - -1. **Service Status**: RUNNING -2. **Health Check**: http://localhost:8765/health returns JSON response -3. **Chrome Extension**: Detects service and shows "Windows Service" mode -4. **Printing**: Silent PDF printing works without dialogs - ---- - -**Package Version**: Zero Dependencies Complete -**Last Updated**: September 2025 -**Support**: Check service logs in `%USERPROFILE%\PrintService\logs\` \ No newline at end of file diff --git a/windows_print_service/build_executable.bat b/windows_print_service/build_executable.bat deleted file mode 100644 index cd5f747..0000000 --- a/windows_print_service/build_executable.bat +++ /dev/null @@ -1,26 +0,0 @@ -@echo off -echo Building standalone Windows Print Service executable... - -REM Check if PyInstaller is available -pip show pyinstaller >nul 2>&1 -if %errorLevel% neq 0 ( - echo Installing PyInstaller... - pip install pyinstaller -) - -REM Build standalone executable -echo Creating standalone executable... -pyinstaller --onefile --noconsole --name="QualityPrintService" print_service_complete.py - -if %errorLevel% equ 0 ( - echo. - echo ✓ Executable created successfully! - echo Location: dist\QualityPrintService.exe - echo. - echo You can now distribute the .exe file instead of the Python script - echo Update install_service_complete.bat to use the .exe file -) else ( - echo ERROR: Failed to create executable -) - -pause diff --git a/windows_print_service/build_package.py b/windows_print_service/build_package.py deleted file mode 100644 index b45ef91..0000000 --- a/windows_print_service/build_package.py +++ /dev/null @@ -1,586 +0,0 @@ -#!/usr/bin/env python3 -""" -Build script to create a complete self-contained Windows Print Service package -This script prepares all dependencies and creates the distribution package -""" - -import os -import shutil -import zipfile -import sys -import subprocess -import tempfile -from pathlib import Path - -def create_portable_python_package(): - """Create instructions for portable Python package.""" - instructions = """ -# PORTABLE PYTHON PACKAGE INSTRUCTIONS - -To create a complete self-contained package, you need to include a portable Python interpreter. - -## Option 1: Download Embedded Python (Recommended) -1. Download Python 3.11 Embedded from: https://www.python.org/downloads/windows/ -2. Choose "Windows embeddable package (64-bit)" or "(32-bit)" -3. Extract to a folder named 'python_portable' -4. The structure should be: - python_portable/ - ├── python.exe - ├── python311.dll (or similar) - ├── pythoncom311.dll - └── ... (other Python files) - -## Option 2: Use PyInstaller (Alternative) -1. Install PyInstaller: pip install pyinstaller -2. Run: pyinstaller --onefile --noconsole print_service_complete.py -3. This creates a single .exe file with all dependencies - -## Option 3: Manual Python Installation Check -The installer will check for system Python and use it if available. - -## Current Package Structure -This package includes: -✓ Complete Python script with all dependencies -✓ Windows service installer -✓ Chrome extension -✓ Logging and error handling -✓ Multiple printing method fallbacks -✓ Automatic recovery options - -## Dependencies Included in Python Script: -- All standard library modules (http.server, json, subprocess, etc.) -- No external dependencies required -- Pure Python implementation - -The service will work with any Python 3.7+ installation. -""" - - with open('PORTABLE_PYTHON_INSTRUCTIONS.txt', 'w') as f: - f.write(instructions) - - print("✓ Created portable Python instructions") - -def create_build_executable_script(): - """Create script to build standalone executable.""" - build_script = """@echo off -echo Building standalone Windows Print Service executable... - -REM Check if PyInstaller is available -pip show pyinstaller >nul 2>&1 -if %errorLevel% neq 0 ( - echo Installing PyInstaller... - pip install pyinstaller -) - -REM Build standalone executable -echo Creating standalone executable... -pyinstaller --onefile --noconsole --name="QualityPrintService" print_service_complete.py - -if %errorLevel% equ 0 ( - echo. - echo ✓ Executable created successfully! - echo Location: dist\\QualityPrintService.exe - echo. - echo You can now distribute the .exe file instead of the Python script - echo Update install_service_complete.bat to use the .exe file -) else ( - echo ERROR: Failed to create executable -) - -pause -""" - - with open('build_executable.bat', 'w') as f: - f.write(build_script) - - print("✓ Created executable build script") - -def create_complete_readme(): - """Create comprehensive README for the package.""" - readme_content = """# Quality Windows Print Service - Complete Self-Contained Package - -## 🎯 Overview -This is a complete, self-contained Windows print service for Quality Label system with zero external dependencies. - -## 📦 Package Contents - -### Core Files: -- `print_service_complete.py` - Main Python service (uses only standard library) -- `install_service_complete.bat` - Complete installer (run as Administrator) -- `uninstall_service_complete.bat` - Complete uninstaller -- `requirements_complete.txt` - Dependencies list (all standard library) - -### Chrome Extension: -- `chrome_extension/` - Complete Chrome extension for web integration -- `chrome_extension/manifest.json` - Extension configuration -- `chrome_extension/background.js` - Service communication -- `chrome_extension/popup.html` - Extension interface - -### Documentation: -- `README.md` - This file -- `PORTABLE_PYTHON_INSTRUCTIONS.txt` - Guide for Python distribution -- `INSTALLATION_COMPLETE.md` - Detailed installation guide - -### Optional Build Tools: -- `build_executable.bat` - Creates standalone .exe (requires PyInstaller) -- `build_package.py` - Package builder script - -## 🚀 Quick Installation (5 Minutes) - -### Prerequisites: -- Windows 10/11 or Windows Server 2016+ -- Administrator privileges -- Python 3.7+ (or use included portable Python) -- Google Chrome browser - -### Steps: -1. **Extract Package**: Extract all files to a temporary location -2. **Run Installer**: Right-click `install_service_complete.bat` → "Run as administrator" -3. **Install Extension**: Load `chrome_extension` folder in Chrome (chrome://extensions/) -4. **Test Service**: Visit http://localhost:8765/health - -## 🔧 Technical Details - -### Service Architecture: -``` -Web App → Chrome Extension → Windows Service → Printer -``` - -### Features: -- ✅ Pure Python implementation (standard library only) -- ✅ Multiple printing methods (Adobe Reader, SumatraPDF, PowerShell, Edge, System Default) -- ✅ Automatic service recovery and restart -- ✅ Comprehensive logging system -- ✅ Cross-printer compatibility -- ✅ Zero external dependencies -- ✅ Windows service integration -- ✅ Chrome extension communication - -### Service Endpoints: -- `GET /health` - Service health check -- `GET /printers` - List available printers -- `GET /status` - Service status and statistics -- `POST /print_pdf` - Print PDF file - -### Printing Methods (Fallback Chain): -1. Adobe Reader command line -2. SumatraPDF automation -3. PowerShell printing -4. Microsoft Edge integration -5. System default application - -## 🛠️ Advanced Configuration - -### Service Configuration: -- Service Name: `QualityPrintService` -- Display Name: `Quality Label Print Service` -- Installation Path: `C:\\QualityPrintService\\` -- Log Directory: `%USERPROFILE%\\PrintService\\logs\\` -- Port: `8765` (localhost only) - -### Logging: -- Daily log rotation -- Separate error and output logs -- Configurable log levels -- Automatic cleanup - -### Recovery Options: -- Auto-restart on failure (3 attempts) -- 5-second delay between restarts -- 24-hour reset period -- Scheduled task fallback - -## 🐛 Troubleshooting - -### Service Won't Start: -1. Check Windows Event Viewer -2. Verify Python installation -3. Check port 8765 availability -4. Run as Administrator - -### Printing Issues: -1. Verify printer installation -2. Check printer permissions -3. Test with different print methods -4. Review service logs - -### Extension Issues: -1. Reload extension in Chrome -2. Check extension permissions -3. Verify service connectivity -4. Clear browser cache - -### Common Solutions: -```bash -# Check service status -sc query QualityPrintService - -# Restart service -sc stop QualityPrintService -sc start QualityPrintService - -# Test connectivity -curl http://localhost:8765/health - -# View logs -type "%USERPROFILE%\\PrintService\\logs\\print_service_*.log" -``` - -## 📋 System Requirements - -### Minimum Requirements: -- Windows 10 (1903) or Windows Server 2016 -- 50 MB free disk space -- Python 3.7+ (can be portable) -- Chrome/Edge browser -- Local printer access - -### Recommended: -- Windows 10/11 (latest) -- 100 MB free disk space -- Python 3.9+ -- Administrative privileges -- Network printer access - -## 🔒 Security Notes -- Service runs on localhost only (127.0.0.1:8765) -- No external network access required -- Uses Windows authentication -- Temporary files auto-cleanup -- Secure PDF handling - -## 🚀 Performance -- Memory usage: ~15-30 MB -- CPU usage: <1% (idle) -- Startup time: ~2 seconds -- Print processing: ~1-3 seconds per job - -## 📞 Support -For issues or questions: -1. Check this README -2. Review log files -3. Test with different browsers -4. Verify printer connectivity - -## 📝 License -Internal use only - Quality Label System -""" - - with open('README_COMPLETE.md', 'w') as f: - f.write(readme_content) - - print("✓ Created comprehensive README") - -def create_installation_guide(): - """Create detailed installation guide.""" - guide_content = """# Quality Print Service - Complete Installation Guide - -## 🎯 Pre-Installation Checklist - -### System Requirements Verification: -- [ ] Windows 10 build 1903+ or Windows Server 2016+ -- [ ] Administrator access to the system -- [ ] Google Chrome browser installed -- [ ] At least 100 MB free disk space -- [ ] Network/USB printer connected and configured - -### Python Requirements: -- [ ] Python 3.7+ installed OR use included portable Python -- [ ] Python accessible via command line (optional) - -## 📦 Installation Methods - -### Method 1: Complete Automatic Installation (Recommended) - -1. **Download and Extract**: - - Extract the complete package to any folder (e.g., Desktop) - - No need to keep the files permanently - -2. **Run Installer**: - ``` - Right-click: install_service_complete.bat - Select: "Run as administrator" - ``` - -3. **Follow Installation Steps**: - ``` - [1/6] Administrator privileges confirmed ✓ - [2/6] Checking Python installation... - [3/6] Creating installation directories... - [4/6] Installing service files... - [5/6] Installing Windows service... - [6/6] Starting service... - ``` - -4. **Install Chrome Extension**: - - Chrome will open the extension folder automatically - - Go to `chrome://extensions/` - - Enable "Developer mode" (top right) - - Click "Load unpacked" - - Select the `chrome_extension` folder - -5. **Verify Installation**: - - Visit: `http://localhost:8765/health` - - Expected response: `{"status": "healthy"}` - -### Method 2: Manual Installation - -1. **Create Directories**: - ```cmd - mkdir C:\QualityPrintService - mkdir %USERPROFILE%\PrintService\logs - ``` - -2. **Copy Files**: - ```cmd - copy print_service_complete.py C:\QualityPrintService\ - ``` - -3. **Install Service**: - ```cmd - sc create QualityPrintService binPath="python C:\QualityPrintService\print_service_complete.py" - sc start QualityPrintService - ``` - -## 🔧 Post-Installation Configuration - -### Service Verification: -```cmd -# Check service status -sc query QualityPrintService - -# Check service configuration -sc qc QualityPrintService - -# View service logs (if using NSSM) -type "%USERPROFILE%\PrintService\logs\service_output.log" -``` - -### Network Testing: -```powershell -# Test health endpoint -Invoke-RestMethod -Uri http://localhost:8765/health - -# Test printer endpoint -Invoke-RestMethod -Uri http://localhost:8765/printers - -# Test from browser -start http://localhost:8765/status -``` - -### Chrome Extension Setup: -1. Open Chrome browser -2. Navigate to `chrome://extensions/` -3. Enable "Developer mode" toggle (top-right corner) -4. Click "Load unpacked" button -5. Browse and select the `chrome_extension` folder -6. Verify extension appears in the list with green toggle - -## 🔍 Installation Verification - -### Health Check Procedure: -1. **Service Status**: Verify Windows service is running - ```cmd - sc query QualityPrintService | find "RUNNING" - ``` - -2. **Network Connectivity**: Test HTTP endpoints - ```cmd - curl http://localhost:8765/health - ``` - -3. **Printer Detection**: Check printer enumeration - ```cmd - curl http://localhost:8765/printers - ``` - -4. **Extension Communication**: Test from web page - - Open the Quality app in Chrome - - Go to print module - - Verify "Extension ready" status - -### Expected Responses: - -**Health Check**: -```json -{ - "status": "healthy", - "service": "Windows Print Service", - "version": "1.0.0", - "timestamp": "2025-09-25T10:30:00" -} -``` - -**Printer List**: -```json -{ - "success": true, - "printers": [ - {"name": "HP LaserJet", "type": "Local", "status": "Available"} - ], - "count": 1 -} -``` - -## 🚨 Troubleshooting Common Issues - -### Issue: "Administrator privileges required" -**Solution**: -- Right-click installer file -- Select "Run as administrator" -- Confirm UAC prompt - -### Issue: "Python not found" -**Solutions**: -1. Install Python from python.org -2. Use included portable Python -3. Add Python to system PATH - -### Issue: "Service failed to start" -**Solutions**: -1. Check Windows Event Viewer: - - Windows Logs → Application - - Filter by source: "Service Control Manager" -2. Verify port 8765 is not in use: - ```cmd - netstat -an | find "8765" - ``` -3. Check service logs: - ```cmd - type "%USERPROFILE%\PrintService\logs\print_service_*.log" - ``` - -### Issue: "Chrome extension not working" -**Solutions**: -1. Reload extension in `chrome://extensions/` -2. Check extension permissions -3. Verify service is responding at `localhost:8765` -4. Clear browser cache and cookies - -### Issue: "PDF printing fails" -**Solutions**: -1. Install Adobe Reader or SumatraPDF -2. Check printer permissions -3. Verify PDF file accessibility -4. Test with different printer - -## 🔄 Maintenance and Updates - -### Regular Maintenance: -- **Log Cleanup**: Logs rotate automatically -- **Service Monitoring**: Check service status weekly -- **Chrome Extension**: Update when prompted - -### Manual Service Management: -```cmd -# Stop service -sc stop QualityPrintService - -# Start service -sc start QualityPrintService - -# Restart service -sc stop QualityPrintService && timeout /t 3 && sc start QualityPrintService - -# Change startup type -sc config QualityPrintService start= auto -``` - -### Log File Locations: -- Service logs: `%USERPROFILE%\PrintService\logs\` -- Windows Event Logs: Event Viewer → Windows Logs → Application -- Chrome Extension: Chrome DevTools → Console - -## 🔧 Advanced Configuration - -### Custom Port Configuration: -Edit `print_service_complete.py`: -```python -server_address = ('localhost', 8765) # Change 8765 to desired port -``` - -### Custom Install Directory: -Edit `install_service_complete.bat`: -```batch -set INSTALL_DIR=C:\CustomPath\PrintService -``` - -### Service Recovery Options: -```cmd -sc failure QualityPrintService reset= 86400 actions= restart/5000/restart/10000/restart/30000 -``` - -## 📋 Uninstallation - -### Complete Removal: -1. Run `uninstall_service_complete.bat` as Administrator -2. Remove Chrome extension manually -3. Optional: Delete log files - -### Manual Removal: -```cmd -# Stop and remove service -sc stop QualityPrintService -sc delete QualityPrintService - -# Remove files -rmdir /s /q C:\QualityPrintService -rmdir /s /q "%USERPROFILE%\PrintService" -``` - -## 📞 Getting Help - -### Before Contacting Support: -1. Check this installation guide -2. Review troubleshooting section -3. Check service logs for error messages -4. Test with simple printer (like Microsoft Print to PDF) - -### Information to Provide: -- Windows version (run `winver`) -- Python version (run `python --version`) -- Service status (run `sc query QualityPrintService`) -- Recent log entries -- Error messages or screenshots - ---- -**Installation Guide Version**: 1.0.0 -**Last Updated**: September 2025 -**Support**: Internal Quality System Team -""" - - with open('INSTALLATION_COMPLETE.md', 'w') as f: - f.write(guide_content) - - print("✓ Created detailed installation guide") - -def build_complete_package(): - """Build the complete package with all dependencies.""" - print("Building complete Windows Print Service package...") - - # Create documentation files - create_portable_python_package() - create_build_executable_script() - create_complete_readme() - create_installation_guide() - - print("\n✓ Complete package prepared!") - print("\nFiles created:") - print(" ✓ print_service_complete.py - Main service with all dependencies") - print(" ✓ install_service_complete.bat - Complete installer") - print(" ✓ uninstall_service_complete.bat - Complete uninstaller") - print(" ✓ requirements_complete.txt - Dependencies list") - print(" ✓ README_COMPLETE.md - Comprehensive documentation") - print(" ✓ INSTALLATION_COMPLETE.md - Detailed installation guide") - print(" ✓ PORTABLE_PYTHON_INSTRUCTIONS.txt - Python distribution guide") - print(" ✓ build_executable.bat - Executable builder") - - print("\nNext steps:") - print("1. Include a portable Python distribution (see PORTABLE_PYTHON_INSTRUCTIONS.txt)") - print("2. Test the complete package on a clean Windows system") - print("3. Package everything into the download ZIP") - - return True - -if __name__ == "__main__": - build_complete_package() \ No newline at end of file diff --git a/windows_print_service/chrome_extension/background.js b/windows_print_service/chrome_extension/background.js deleted file mode 100644 index 7f32fff..0000000 --- a/windows_print_service/chrome_extension/background.js +++ /dev/null @@ -1,307 +0,0 @@ -/** - * Quality Label Printing Extension - Windows Service Communication - * Communicates with local Windows print service for silent printing - */ - -console.log('Quality Label Printing Extension - Windows Service Mode'); - -// Service configuration -const PRINT_SERVICE_URL = 'http://localhost:8765'; -const SERVICE_TIMEOUT = 30000; // 30 seconds - -// Initialize extension -chrome.runtime.onInstalled.addListener(() => { - console.log('Quality Label Printing Service extension installed - Windows Service Mode'); - testServiceConnection(); -}); - -// Test connection to Windows service -async function testServiceConnection() { - try { - const response = await fetch(`${PRINT_SERVICE_URL}/health`, { - method: 'GET', - timeout: 5000 - }); - - if (response.ok) { - const data = await response.json(); - console.log('✅ Windows Print Service connected:', data); - return true; - } else { - console.warn('⚠️ Windows Print Service not responding:', response.status); - return false; - } - } catch (error) { - console.warn('❌ Windows Print Service not available:', error.message); - return false; - } -} - -// Handle messages from content scripts or web pages -chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { - console.log('Background script received message:', message); - - switch (message.action) { - case 'print_pdf': - handleWindowsServicePrint(message) - .then(result => { - console.log('Windows service print completed:', result); - sendResponse(result); - }) - .catch(error => { - console.error('Windows service print error:', error); - sendResponse({ success: false, error: error.message }); - }); - return true; // Keep message channel open for async response - - case 'get_printers': - getAvailablePrinters() - .then(printers => { - sendResponse({ success: true, printers: printers }); - }) - .catch(error => { - console.error('Error getting printers:', error); - sendResponse({ - success: false, - error: error.message, - printers: [{ name: 'default', display_name: 'Default Printer', is_default: true }] - }); - }); - return true; - - case 'ping': - testServiceConnection() - .then(connected => { - sendResponse({ - success: true, - extension_version: chrome.runtime.getManifest().version, - ready: true, - service_connected: connected, - mode: 'windows_service' - }); - }) - .catch(() => { - sendResponse({ - success: true, - extension_version: chrome.runtime.getManifest().version, - ready: false, - service_connected: false, - mode: 'windows_service' - }); - }); - return true; - - default: - sendResponse({ error: 'Unknown action', success: false }); - } -}); - -// Handle external messages from web pages -chrome.runtime.onMessageExternal.addListener((message, sender, sendResponse) => { - console.log('External message received:', message, 'from:', sender); - - // Verify sender origin for security - const allowedOrigins = [ - 'http://localhost:5000', - 'http://localhost:8000', - 'http://127.0.0.1:5000', - 'http://127.0.0.1:8000', - 'http://localhost:3000', - 'http://localhost:8080' - ]; - - if (!allowedOrigins.some(origin => sender.url && sender.url.startsWith(origin))) { - console.warn('Unauthorized origin:', sender.url); - sendResponse({ error: 'Unauthorized origin', success: false }); - return; - } - - // Handle the message - switch (message.action) { - case 'print_pdf': - handleWindowsServicePrint(message) - .then(result => sendResponse(result)) - .catch(error => { - console.error('Print PDF error:', error); - sendResponse({ success: false, error: error.message }); - }); - return true; - - case 'ping': - testServiceConnection() - .then(connected => { - sendResponse({ - success: true, - extension_version: chrome.runtime.getManifest().version, - ready: true, - service_connected: connected, - mode: 'windows_service' - }); - }) - .catch(() => { - sendResponse({ - success: true, - extension_version: chrome.runtime.getManifest().version, - ready: false, - service_connected: false, - mode: 'windows_service' - }); - }); - return true; - - default: - sendResponse({ error: 'Unknown action', success: false }); - } -}); - -/** - * Get available printers from Windows service - */ -async function getAvailablePrinters() { - try { - const response = await fetch(`${PRINT_SERVICE_URL}/printers`, { - method: 'GET', - timeout: 10000 - }); - - if (response.ok) { - const data = await response.json(); - return data.printers || []; - } else { - throw new Error(`Service responded with status: ${response.status}`); - } - } catch (error) { - console.error('Failed to get printers from service:', error); - throw error; - } -} - -/** - * Handle PDF printing via Windows Service - */ -async function handleWindowsServicePrint(message) { - console.log('🖨️ Sending PDF to Windows print service:', message); - - try { - const { pdfUrl, orderId, prodOrder, quantity, printerName } = message; - - if (!pdfUrl) { - throw new Error('PDF URL is required'); - } - - // First, test if service is available - const serviceAvailable = await testServiceConnection(); - if (!serviceAvailable) { - throw new Error('Windows Print Service is not running. Please ensure the service is installed and started.'); - } - - // Prepare print request - const printRequest = { - pdf_url: pdfUrl, - printer_name: printerName || 'default', - order_id: orderId, - prod_order: prodOrder, - quantity: quantity, - timestamp: new Date().toISOString() - }; - - console.log('📤 Sending print request to service:', printRequest); - - // Send PDF to Windows service for printing - const response = await fetch(`${PRINT_SERVICE_URL}/print_pdf`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(printRequest) - }); - - if (!response.ok) { - const errorText = await response.text(); - throw new Error(`Print service error (${response.status}): ${errorText}`); - } - - const result = await response.json(); - - if (result.success) { - console.log('✅ Print job sent successfully:', result); - - return { - success: true, - message: `PDF sent to ${result.printer || printerName || 'default printer'} successfully`, - method: result.method || 'Windows Print Service', - printer: result.printer || printerName, - orderId: orderId, - instruction: 'PDF has been sent to the printer queue' - }; - } else { - throw new Error(result.error || 'Unknown print service error'); - } - - } catch (error) { - console.error('❌ Windows service print failed:', error); - - // Fallback: Return instruction to print manually - return { - success: false, - error: error.message, - fallback: true, - instruction: 'Windows service unavailable. Please download and print the PDF manually.' - }; - } -} - -/** - * Fallback function for when Windows service is not available - */ -async function handleFallbackPrint(message) { - console.log('🔄 Using fallback print method:', message); - - try { - const { pdfUrl, orderId, prodOrder, quantity } = message; - - // Create a new tab with the PDF - const tab = await chrome.tabs.create({ - url: pdfUrl, - active: false // Don't switch to the tab - }); - - // Wait a moment for PDF to load - await new Promise(resolve => setTimeout(resolve, 2000)); - - // Get the created tab - const updatedTab = await chrome.tabs.get(tab.id); - - return { - success: true, - message: `PDF opened in new tab for manual printing`, - method: 'Manual Print Fallback', - tabId: tab.id, - instruction: 'PDF opened in new tab. Use Ctrl+P to print or close the tab if not needed.' - }; - - } catch (error) { - console.error('❌ Fallback print failed:', error); - throw error; - } -} - -// Utility functions -function delay(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -// Extension startup -console.log('🖨️ Quality Label Printing Extension loaded - Windows Service Mode'); -console.log(`🔗 Service URL: ${PRINT_SERVICE_URL}`); - -// Test service on startup -testServiceConnection().then(connected => { - if (connected) { - console.log('✅ Windows Print Service is available'); - } else { - console.log('⚠️ Windows Print Service is not available - fallback mode active'); - } -}); - -console.log('✅ Background script loaded successfully - Platform safe mode enabled'); \ No newline at end of file diff --git a/windows_print_service/chrome_extension/content.js b/windows_print_service/chrome_extension/content.js deleted file mode 100644 index 9a90198..0000000 --- a/windows_print_service/chrome_extension/content.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Quality Label Printing Service - Content Script - * Simplified injection for extension ID detection - */ - -console.log('Quality Label Printing - Content Script Loaded'); - -// Inject extension ID into DOM for web page detection -function injectExtensionId() { - // Remove any existing extension ID element - const existingElement = document.getElementById('chrome-extension-id'); - if (existingElement) { - existingElement.remove(); - } - - // Create new element with extension ID - const extensionIdElement = document.createElement('div'); - extensionIdElement.id = 'chrome-extension-id'; - extensionIdElement.setAttribute('data-extension-id', chrome.runtime.id); - extensionIdElement.style.display = 'none'; - - // Add to document head or body - (document.head || document.body || document.documentElement).appendChild(extensionIdElement); - - console.log('Extension ID injected:', chrome.runtime.id); -} - -// Inject extension ID when DOM is ready -if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', injectExtensionId); -} else { - injectExtensionId(); -} - -// Also inject when page changes (for SPAs) -if (window.navigation) { - navigation.addEventListener('navigate', injectExtensionId); -} else { - // Fallback for older browsers - let lastUrl = location.href; - new MutationObserver(() => { - const url = location.href; - if (url !== lastUrl) { - lastUrl = url; - setTimeout(injectExtensionId, 100); - } - }).observe(document, { subtree: true, childList: true }); -} \ No newline at end of file diff --git a/windows_print_service/chrome_extension/icons/README.md b/windows_print_service/chrome_extension/icons/README.md deleted file mode 100644 index 5a5a982..0000000 --- a/windows_print_service/chrome_extension/icons/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Placeholder for icon files - in production, add actual PNG icons: -# - icon16.png (16x16 pixels) -# - icon48.png (48x48 pixels) -# - icon128.png (128x128 pixels) - -# For now, create simple text-based icons using SVG converted to PNG -# These should be replaced with proper icons later \ No newline at end of file diff --git a/windows_print_service/chrome_extension/icons/create_icons.py b/windows_print_service/chrome_extension/icons/create_icons.py deleted file mode 100644 index a051067..0000000 --- a/windows_print_service/chrome_extension/icons/create_icons.py +++ /dev/null @@ -1,27 +0,0 @@ -# Simple text-based icons for the Chrome extension -# These are placeholder files - replace with actual PNG icons for production - -# Create simple SVG icons that can be converted to PNG -ICON_16_SVG = ''' - - - 🖨 - -''' - -ICON_48_SVG = ''' - - - 🖨️ - -''' - -ICON_128_SVG = ''' - - - 🖨️ - -''' - -# For now, create simple text placeholders -# In production, convert these SVGs to PNG files \ No newline at end of file diff --git a/windows_print_service/chrome_extension/icons/generate_icons.py b/windows_print_service/chrome_extension/icons/generate_icons.py deleted file mode 100644 index ad8ef3b..0000000 --- a/windows_print_service/chrome_extension/icons/generate_icons.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python3 -""" -Generate PNG icons for Chrome extension -Creates simple colored squares with printer icons -""" - -try: - from PIL import Image, ImageDraw, ImageFont - PIL_AVAILABLE = True -except ImportError: - PIL_AVAILABLE = False - -import os - -def create_simple_icon(size, filename): - """Create a simple colored square icon""" - if PIL_AVAILABLE: - # Create image with PIL - img = Image.new('RGBA', (size, size), (0, 123, 255, 255)) # Blue background - draw = ImageDraw.Draw(img) - - # Add a white border - border_width = max(1, size // 16) - draw.rectangle([0, 0, size-1, size-1], outline=(255, 255, 255, 255), width=border_width) - - # Add text (P for Print) - try: - font_size = size // 2 - font = ImageFont.load_default() - text = "P" - bbox = draw.textbbox((0, 0), text, font=font) - text_width = bbox[2] - bbox[0] - text_height = bbox[3] - bbox[1] - x = (size - text_width) // 2 - y = (size - text_height) // 2 - draw.text((x, y), text, fill=(255, 255, 255, 255), font=font) - except: - pass - - img.save(filename, 'PNG') - print(f"Created {filename} ({size}x{size})") - else: - # Create a minimal PNG file without PIL - create_minimal_png(size, filename) - -def create_minimal_png(size, filename): - """Create a minimal PNG file without PIL""" - # This creates a very basic PNG file - # Blue square with minimal PNG structure - - import struct - import zlib - - # PNG signature - png_signature = b'\x89PNG\r\n\x1a\n' - - # IHDR chunk - width = height = size - bit_depth = 8 - color_type = 2 # RGB - compression = 0 - filter_method = 0 - interlace = 0 - - ihdr_data = struct.pack('>IIBBBBB', width, height, bit_depth, color_type, compression, filter_method, interlace) - ihdr_crc = zlib.crc32(b'IHDR' + ihdr_data) & 0xffffffff - ihdr_chunk = struct.pack('>I', len(ihdr_data)) + b'IHDR' + ihdr_data + struct.pack('>I', ihdr_crc) - - # IDAT chunk (blue pixels) - pixels = [] - for y in range(height): - row = [0] # Filter byte - for x in range(width): - # Blue color RGB(0, 123, 255) - row.extend([0, 123, 255]) - pixels.extend(row) - - pixel_data = bytes(pixels) - compressed_data = zlib.compress(pixel_data) - idat_crc = zlib.crc32(b'IDAT' + compressed_data) & 0xffffffff - idat_chunk = struct.pack('>I', len(compressed_data)) + b'IDAT' + compressed_data + struct.pack('>I', idat_crc) - - # IEND chunk - iend_crc = zlib.crc32(b'IEND') & 0xffffffff - iend_chunk = struct.pack('>I', 0) + b'IEND' + struct.pack('>I', iend_crc) - - # Write PNG file - with open(filename, 'wb') as f: - f.write(png_signature) - f.write(ihdr_chunk) - f.write(idat_chunk) - f.write(iend_chunk) - - print(f"Created minimal {filename} ({size}x{size})") - -def main(): - # Create icons directory if it doesn't exist - icons_dir = "/home/ske087/quality_recticel/windows_print_service/chrome_extension/icons" - - print("Creating Chrome extension icons...") - print(f"PIL available: {PIL_AVAILABLE}") - - # Create required icon sizes - sizes = [16, 32, 48, 128] - - for size in sizes: - filename = os.path.join(icons_dir, f"icon{size}.png") - create_simple_icon(size, filename) - - print("✅ All icons created successfully!") - print("\nIcons created:") - for size in sizes: - filename = f"icon{size}.png" - filepath = os.path.join(icons_dir, filename) - if os.path.exists(filepath): - file_size = os.path.getsize(filepath) - print(f" ✓ {filename} ({size}x{size}px, {file_size} bytes)") - else: - print(f" ✗ {filename} - FAILED") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/windows_print_service/chrome_extension/icons/icon128.png b/windows_print_service/chrome_extension/icons/icon128.png deleted file mode 100644 index 453260a..0000000 Binary files a/windows_print_service/chrome_extension/icons/icon128.png and /dev/null differ diff --git a/windows_print_service/chrome_extension/icons/icon128.txt b/windows_print_service/chrome_extension/icons/icon128.txt deleted file mode 100644 index 6b301ee..0000000 --- a/windows_print_service/chrome_extension/icons/icon128.txt +++ /dev/null @@ -1,4 +0,0 @@ -# Placeholder for 128x128 icon -# This is a text file placeholder -# Replace with actual icon128.png file -🖨️ \ No newline at end of file diff --git a/windows_print_service/chrome_extension/icons/icon16.png b/windows_print_service/chrome_extension/icons/icon16.png deleted file mode 100644 index 7bb5323..0000000 Binary files a/windows_print_service/chrome_extension/icons/icon16.png and /dev/null differ diff --git a/windows_print_service/chrome_extension/icons/icon16.txt b/windows_print_service/chrome_extension/icons/icon16.txt deleted file mode 100644 index 8b2cace..0000000 --- a/windows_print_service/chrome_extension/icons/icon16.txt +++ /dev/null @@ -1,4 +0,0 @@ -# Placeholder for 16x16 icon -# This is a text file placeholder -# Replace with actual icon16.png file -🖨️ \ No newline at end of file diff --git a/windows_print_service/chrome_extension/icons/icon32.png b/windows_print_service/chrome_extension/icons/icon32.png deleted file mode 100644 index 6f898d4..0000000 Binary files a/windows_print_service/chrome_extension/icons/icon32.png and /dev/null differ diff --git a/windows_print_service/chrome_extension/icons/icon48.png b/windows_print_service/chrome_extension/icons/icon48.png deleted file mode 100644 index 293aa25..0000000 Binary files a/windows_print_service/chrome_extension/icons/icon48.png and /dev/null differ diff --git a/windows_print_service/chrome_extension/icons/icon48.txt b/windows_print_service/chrome_extension/icons/icon48.txt deleted file mode 100644 index 521d5ba..0000000 --- a/windows_print_service/chrome_extension/icons/icon48.txt +++ /dev/null @@ -1,4 +0,0 @@ -# Placeholder for 48x48 icon -# This is a text file placeholder -# Replace with actual icon48.png file -🖨️ \ No newline at end of file diff --git a/windows_print_service/chrome_extension/manifest.json b/windows_print_service/chrome_extension/manifest.json deleted file mode 100644 index 881dac1..0000000 --- a/windows_print_service/chrome_extension/manifest.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "manifest_version": 3, - "name": "Quality Label Printing Service", - "version": "1.0.0", - "description": "Simple silent PDF printing for Quality Label Printing application", - - "permissions": [ - "activeTab", - "storage", - "downloads", - "tabs", - "scripting" - ], - - "host_permissions": [ - "http://localhost:*/*", - "https://localhost:*/*", - "http://*/*", - "https://*/*" - ], - - "background": { - "service_worker": "background.js" - }, - - "content_scripts": [{ - "matches": [""], - "js": ["content.js"], - "run_at": "document_end" - }], - - "action": { - "default_popup": "popup.html", - "default_title": "Quality Label Printing Service", - "default_icon": { - "16": "icons/icon16.png", - "32": "icons/icon32.png", - "48": "icons/icon48.png", - "128": "icons/icon128.png" - } - }, - - "icons": { - "16": "icons/icon16.png", - "32": "icons/icon32.png", - "48": "icons/icon48.png", - "128": "icons/icon128.png" - }, - - "web_accessible_resources": [{ - "resources": ["content.js"], - "matches": [""] - }], - - "externally_connectable": { - "matches": [ - "http://localhost:*/*", - "https://localhost:*/*" - ] - } -} \ No newline at end of file diff --git a/windows_print_service/chrome_extension/popup.html b/windows_print_service/chrome_extension/popup.html deleted file mode 100644 index f6ff5b6..0000000 --- a/windows_print_service/chrome_extension/popup.html +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - -
- -
Quality Label Printing Service
-
Version 1.0.0
-
- -
-
Checking service status...
-
- - - - - - - - \ No newline at end of file diff --git a/windows_print_service/chrome_extension/popup.js b/windows_print_service/chrome_extension/popup.js deleted file mode 100644 index c948c49..0000000 --- a/windows_print_service/chrome_extension/popup.js +++ /dev/null @@ -1,261 +0,0 @@ -/** - * Quality Label Printing Service - Popup Script - * Manages the extension popup interface - */ - -document.addEventListener('DOMContentLoaded', async () => { - console.log('Popup loaded'); - - // Get elements - const elements = { - loading: document.getElementById('loading'), - content: document.getElementById('content'), - serviceStatus: document.getElementById('service-status'), - statusMessage: document.getElementById('status-message'), - statusDetail: document.getElementById('status-detail'), - refreshBtn: document.getElementById('refresh-btn'), - testPrintBtn: document.getElementById('test-print-btn'), - getPrintersBtn: document.getElementById('get-printers-btn'), - printersContainer: document.getElementById('printers-container'), - printersList: document.getElementById('printers-list'), - helpLink: document.getElementById('help-link') - }; - - // Initialize popup - await initializePopup(); - - // Event listeners - elements.refreshBtn.addEventListener('click', checkServiceStatus); - elements.testPrintBtn.addEventListener('click', testPrint); - elements.getPrintersBtn.addEventListener('click', getPrinters); - elements.helpLink.addEventListener('click', showHelp); - - /** - * Initialize popup - */ - async function initializePopup() { - try { - await checkServiceStatus(); - - // Show content, hide loading - elements.loading.classList.add('hidden'); - elements.content.classList.remove('hidden'); - - } catch (error) { - console.error('Initialization error:', error); - showError('Failed to initialize popup'); - } - } - - /** - * Check service status - */ - async function checkServiceStatus() { - try { - elements.refreshBtn.disabled = true; - elements.refreshBtn.textContent = 'Checking...'; - - // Send message to background script - const result = await new Promise((resolve) => { - chrome.runtime.sendMessage({ action: 'check_service' }, resolve); - }); - - updateServiceStatus(result); - - } catch (error) { - console.error('Service check error:', error); - showError('Failed to check service status'); - } finally { - elements.refreshBtn.disabled = false; - elements.refreshBtn.textContent = 'Refresh Status'; - } - } - - /** - * Update service status display - */ - function updateServiceStatus(result) { - const statusCard = elements.serviceStatus; - const message = elements.statusMessage; - const detail = elements.statusDetail; - - if (result && result.success) { - // Service is available - statusCard.className = 'status-card'; - message.textContent = 'Service is running normally'; - detail.textContent = `Last checked: ${new Date().toLocaleTimeString()}`; - - // Enable buttons - elements.testPrintBtn.disabled = false; - elements.getPrintersBtn.disabled = false; - - } else { - // Service is not available - statusCard.className = 'status-card error'; - message.textContent = 'Service is not available'; - detail.textContent = result ? result.error : 'Unknown error'; - - // Disable buttons - elements.testPrintBtn.disabled = true; - elements.getPrintersBtn.disabled = false; // Keep enabled for diagnostics - } - } - - /** - * Test print functionality - */ - async function testPrint() { - try { - elements.testPrintBtn.disabled = true; - elements.testPrintBtn.textContent = 'Testing...'; - - // Create test PDF data - const testPrintData = { - pdf_url: 'data:application/pdf;base64,JVBERi0xLjQKMSAwIG9iago8PAovVGl0bGUgKFRlc3QgUGFnZSkKL0NyZWF0b3IgKFF1YWxpdHkgUmVjdGljZWwgUHJpbnQgU2VydmljZSkKL1Byb2R1Y2VyIChRdWFsaXR5IFJlY3RpY2VsKQovQ3JlYXRpb25EYXRlIChEOjIwMjMwMTAxMTIwMDAwKQo+PgplbmRvYmoKMiAwIG9iago8PAovVHlwZSAvQ2F0YWxvZwovUGFnZXMgMyAwIFIKPj4KZW5kb2JqCjMgMCBvYmoKPDwKL1R5cGUgL1BhZ2VzCi9LaWRzIFs0IDAgUl0KL0NvdW50IDEKPJ4KZW5kb2JqCjQgMCBvYmoKPDwKL1R5cGUgL1BhZ2UKL1BhcmVudCAzIDAgUgovTWVkaWFCb3ggWzAgMCA2MTIgNzkyXQovQ29udGVudHMgNSAwIFIKL1Jlc291cmNlcyA8PAovRm9udCA8PAovRjEgNiAwIFIKPj4KPj4KPj4KZW5kb2JqCjUgMCBvYmoKPDwKL0xlbmd0aCA0NAo+PgpzdHJlYW0KQlQKL0YxIDEyIFRmCjEwMCA3MDAgVGQKKFRlc3QgUHJpbnQgUGFnZSkgVGoKRVQKZW5kc3RyZWFtCmVuZG9iago2IDAgb2JqCjw8Ci9UeXBlIC9Gb250Ci9TdWJ0eXBlIC9UeXBlMQovQmFzZUZvbnQgL0hlbHZldGljYQo+PgplbmRvYmoKeHJlZgowIDcKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDA5IDAwMDAwIG4gCjAwMDAwMDAxNDggMDAwMDAgbiAKMDAwMDAwMDE5NSAwMDAwMCBuIAowMDAwMDAwMjUyIDAwMDAwIG4gCjAwMDAwMDA0MTQgMDAwMDAgbiAKMDAwMDAwMDUwOCAwMDAwMCBuIAp0cmFpbGVyCjw8Ci9TaXplIDcKL1Jvb3QgMiAwIFIKL0luZm8gMSAwIFIKPj4Kc3RhcnR4cmVmCjU2NQolJUVPRgo=', - printer_name: 'default', - copies: 1 - }; - - // Send test print request - const result = await new Promise((resolve) => { - chrome.runtime.sendMessage({ - action: 'print_pdf', - data: testPrintData - }, resolve); - }); - - if (result && result.success) { - showSuccess('Test print sent successfully'); - } else { - showError(result ? result.error : 'Test print failed'); - } - - } catch (error) { - console.error('Test print error:', error); - showError('Test print failed: ' + error.message); - } finally { - elements.testPrintBtn.disabled = false; - elements.testPrintBtn.textContent = 'Test Print'; - } - } - - /** - * Get available printers - */ - async function getPrinters() { - try { - elements.getPrintersBtn.disabled = true; - elements.getPrintersBtn.textContent = 'Loading...'; - - // Get printers from background script - const result = await new Promise((resolve) => { - chrome.runtime.sendMessage({ action: 'get_printers' }, resolve); - }); - - if (result && result.success && result.printers) { - displayPrinters(result.printers); - } else { - showError(result ? result.error : 'Failed to get printers'); - } - - } catch (error) { - console.error('Get printers error:', error); - showError('Failed to get printers: ' + error.message); - } finally { - elements.getPrintersBtn.disabled = false; - elements.getPrintersBtn.textContent = 'Get Printers'; - } - } - - /** - * Display printers list - */ - function displayPrinters(printers) { - if (!printers || printers.length === 0) { - elements.printersList.innerHTML = '
No printers found
'; - } else { - elements.printersList.innerHTML = printers.map(printer => ` -
-
${escapeHtml(printer.name)}
-
- Driver: ${escapeHtml(printer.driver || 'Unknown')}
- Port: ${escapeHtml(printer.port || 'Unknown')} -
-
- `).join(''); - } - - elements.printersContainer.classList.remove('hidden'); - } - - /** - * Show success message - */ - function showSuccess(message) { - const statusCard = elements.serviceStatus; - const statusMessage = elements.statusMessage; - const statusDetail = elements.statusDetail; - - statusCard.className = 'status-card'; - statusMessage.textContent = message; - statusDetail.textContent = new Date().toLocaleTimeString(); - - // Reset after 3 seconds - setTimeout(() => { - checkServiceStatus(); - }, 3000); - } - - /** - * Show error message - */ - function showError(message) { - const statusCard = elements.serviceStatus; - const statusMessage = elements.statusMessage; - const statusDetail = elements.statusDetail; - - statusCard.className = 'status-card error'; - statusMessage.textContent = 'Error: ' + message; - statusDetail.textContent = new Date().toLocaleTimeString(); - } - - /** - * Show help information - */ - function showHelp() { - const helpText = ` -Quality Label Printing Service Help -================================== - -Installation: -1. Install the Windows Print Service using install_service.bat -2. Install this Chrome extension -3. Configure your application to use localhost:8765 - -API Endpoints: -• http://localhost:8765/health - Service health check -• http://localhost:8765/print/pdf - Print PDF files -• http://localhost:8765/print/silent - Silent printing -• http://localhost:8765/printers - Get available printers - -Troubleshooting: -• Ensure Windows service is running -• Check firewall settings (port 8765) -• Verify Chrome extension permissions -• Check service logs: print_service.log - -For support, contact the Quality Label Printing development team. - `; - - alert(helpText.trim()); - } - - /** - * Escape HTML to prevent XSS - */ - function escapeHtml(text) { - const div = document.createElement('div'); - div.textContent = text; - return div.innerHTML; - } -}); \ No newline at end of file diff --git a/windows_print_service/create_portable_package.py b/windows_print_service/create_portable_package.py deleted file mode 100644 index 2e406ea..0000000 --- a/windows_print_service/create_portable_package.py +++ /dev/null @@ -1,424 +0,0 @@ -#!/usr/bin/env python3 -""" -Script to create a completely self-contained Windows Print Service package -with embedded Python distribution and comprehensive Error 1053 fixes -- Zero external dependencies required! -- Multiple installation methods with automatic fallback -- Complete Windows Service Error 1053 resolution -""" - -import os -import sys -import zipfile -import urllib.request -import tempfile -import shutil -from pathlib import Path - -# Python embeddable version details -PYTHON_VERSION = "3.11.9" -PYTHON_DOWNLOAD_URL = f"https://www.python.org/ftp/python/{PYTHON_VERSION}/python-{PYTHON_VERSION}-embed-amd64.zip" -PYTHON_DIR_NAME = "python_embedded" - -def download_portable_python(temp_dir): - """Download and extract Python embedded distribution""" - print(f"📥 Downloading Python {PYTHON_VERSION} embedded distribution...") - - python_zip_path = os.path.join(temp_dir, "python-embed.zip") - - try: - # Download Python embedded - urllib.request.urlretrieve(PYTHON_DOWNLOAD_URL, python_zip_path) - print(f"✅ Downloaded Python to: {python_zip_path}") - - # Create extraction directory - python_extract_dir = os.path.join(temp_dir, PYTHON_DIR_NAME) - os.makedirs(python_extract_dir, exist_ok=True) - - # Extract Python - with zipfile.ZipFile(python_zip_path, 'r') as zip_ref: - zip_ref.extractall(python_extract_dir) - - print(f"✅ Extracted Python to: {python_extract_dir}") - - # Enable site-packages by modifying pth file - pth_files = [f for f in os.listdir(python_extract_dir) if f.endswith('._pth')] - if pth_files: - pth_file = os.path.join(python_extract_dir, pth_files[0]) - with open(pth_file, 'a') as f: - f.write('\nimport site\n') - print("✅ Enabled site-packages in embedded Python") - - return python_extract_dir - - except Exception as e: - print(f"❌ Failed to download Python: {e}") - return None - -def create_complete_package(): - """Create complete self-contained package with embedded Python""" - - # Get current directory (should be windows_print_service) - current_dir = Path(__file__).parent - print(f"📂 Working from: {current_dir}") - - # Create temporary directory - with tempfile.TemporaryDirectory() as temp_dir: - print(f"🔧 Using temporary directory: {temp_dir}") - - # Download and extract portable Python - python_dir = download_portable_python(temp_dir) - if not python_dir: - print("❌ Failed to prepare Python distribution") - return False - - # Create the complete package - package_path = current_dir / "QualityPrintService_COMPLETE_ZERO_DEPENDENCIES.zip" - - print(f"📦 Creating complete package: {package_path}") - - with zipfile.ZipFile(package_path, 'w', zipfile.ZIP_DEFLATED) as zipf: - files_added = 0 - - # Add Python embedded distribution - print("📁 Adding Python embedded distribution...") - for root, dirs, files in os.walk(python_dir): - for file in files: - file_path = os.path.join(root, file) - arcname = os.path.join(PYTHON_DIR_NAME, os.path.relpath(file_path, python_dir)) - zipf.write(file_path, arcname) - files_added += 1 - - # Add all service files - print("📁 Adding service files...") - service_files = [ - "print_service_complete.py", - "service_wrapper.py", - "service_installer.py", - "install_service_complete.bat", - "install_service_ENHANCED.bat", - "uninstall_service_complete.bat", - "fix_error_1053.bat", - "test_service.bat", - "build_executable.bat", - "build_package.py", - "create_portable_package.py", - "requirements_complete.txt", - "INSTALLATION_COMPLETE.md", - "PACKAGE_SUMMARY.md", - "README_COMPLETE.md", - "TROUBLESHOOTING_1053.md", - "ERROR_1053_COMPLETE_FIX.md", - "PORTABLE_PYTHON_INSTRUCTIONS.txt" - ] - - for file_name in service_files: - file_path = current_dir / file_name - if file_path.exists(): - zipf.write(file_path, file_name) - files_added += 1 - print(f" ✅ Added: {file_name}") - - # Add Chrome extension - chrome_ext_dir = current_dir / "chrome_extension" - if chrome_ext_dir.exists(): - print("📁 Adding Chrome extension...") - for root, dirs, files in os.walk(chrome_ext_dir): - for file in files: - if not file.startswith('.'): - file_path = os.path.join(root, file) - arcname = os.path.relpath(file_path, current_dir) - zipf.write(file_path, arcname) - files_added += 1 - - # Create updated installer that uses embedded Python - updated_installer = f'''@echo off -setlocal enabledelayedexpansion - -echo ======================================== -echo Quality Label Print Service Installer -echo ZERO DEPENDENCIES - COMPLETE PACKAGE -echo ======================================== -echo. -echo This package includes EVERYTHING needed: -echo ✅ Embedded Python {PYTHON_VERSION} -echo ✅ Complete Print Service -echo ✅ Windows Service Installer -echo ✅ Chrome Extension -echo ✅ Auto-recovery System -echo. - -REM Check for administrator privileges -net session >nul 2>&1 -if %errorLevel% neq 0 ( - echo ❌ ERROR: Administrator privileges required - echo Please right-click this file and select "Run as administrator" - echo. - pause - exit /b 1 -) - -echo [1/7] Administrator privileges confirmed ✅ -echo. - -REM Set variables -set CURRENT_DIR=%~dp0 -set SERVICE_NAME=QualityPrintService -set SERVICE_DISPLAY_NAME=Quality Label Print Service -set INSTALL_DIR=C:\\QualityPrintService -set PYTHON_EXE=%INSTALL_DIR%\\{PYTHON_DIR_NAME}\\python.exe -set PYTHON_SCRIPT=%INSTALL_DIR%\\print_service_complete.py -set LOG_DIR=%USERPROFILE%\\PrintService\\logs - -echo [2/7] Using embedded Python distribution ✅ -echo Python location: %PYTHON_EXE% -echo. - -REM Stop existing service if running -echo [3/7] Stopping existing service (if any)... -sc query "%SERVICE_NAME%" >nul 2>&1 -if %errorLevel% equ 0 ( - echo Stopping existing service... - net stop "%SERVICE_NAME%" >nul 2>&1 - sc delete "%SERVICE_NAME%" >nul 2>&1 - timeout /t 2 >nul -) -echo Service cleanup completed ✅ -echo. - -REM Create installation directory -echo [4/7] Creating installation directory... -if exist "%INSTALL_DIR%" ( - echo Removing old installation... - rmdir /s /q "%INSTALL_DIR%" >nul 2>&1 -) -mkdir "%INSTALL_DIR%" >nul 2>&1 -echo Installation directory: %INSTALL_DIR% ✅ -echo. - -REM Copy all files to installation directory -echo [5/7] Installing service files... -echo Copying embedded Python... -xcopy "%CURRENT_DIR%{PYTHON_DIR_NAME}" "%INSTALL_DIR%\\{PYTHON_DIR_NAME}\\" /E /I /Y >nul -echo Copying service script... -copy "%CURRENT_DIR%print_service_complete.py" "%INSTALL_DIR%\\" >nul -echo Service files installed ✅ -echo. - -REM Create log directory -echo [6/7] Setting up logging... -mkdir "%LOG_DIR%" >nul 2>&1 -echo Log directory: %LOG_DIR% ✅ -echo. - -REM Install and start Windows service -echo [7/7] Installing Windows service... -sc create "%SERVICE_NAME%" binPath= "\\"%PYTHON_EXE%\\" \\"%PYTHON_SCRIPT%\\"" DisplayName= "%SERVICE_DISPLAY_NAME%" start= auto -if %errorLevel% neq 0 ( - echo ❌ Failed to create Windows service - pause - exit /b 1 -) - -REM Configure service recovery -sc failure "%SERVICE_NAME%" reset= 60 actions= restart/10000/restart/30000/restart/60000 -sc config "%SERVICE_NAME%" depend= "" - -REM Start the service -echo Starting service... -net start "%SERVICE_NAME%" -if %errorLevel% neq 0 ( - echo ⚠️ Service created but failed to start immediately - echo This is normal - the service will start automatically on reboot -) else ( - echo Service started successfully ✅ -) - -echo. -echo ======================================== -echo INSTALLATION COMPLETED! 🎉 -echo ======================================== -echo. -echo ✅ Python embedded distribution installed -echo ✅ Windows Print Service installed and configured -echo ✅ Auto-recovery enabled (restarts on failure) -echo ✅ Service will start automatically on boot -echo. -echo 🌐 Service URL: http://localhost:8765 -echo 📊 Health check: http://localhost:8765/health -echo 📁 Logs location: %LOG_DIR% -echo. -echo 📋 NEXT STEPS: -echo 1. Install Chrome extension from 'chrome_extension' folder -echo 2. Test service: http://localhost:8765/health -echo 3. Configure web application to use service -echo. -echo Press any key to test service connection... -pause >nul - -REM Test service -echo Testing service connection... -timeout /t 3 >nul -curl -s http://localhost:8765/health >nul 2>&1 -if %errorLevel% equ 0 ( - echo ✅ Service is responding correctly! -) else ( - echo ⚠️ Service test failed - may need a moment to start - echo Check logs in: %LOG_DIR% -) - -echo. -echo Installation complete! Service is ready to use. -pause -''' - - # Add the updated installer - zipf.writestr("install_service_ZERO_DEPENDENCIES.bat", updated_installer) - files_added += 1 - - # Add comprehensive README - readme_content = f'''# Quality Print Service - ZERO DEPENDENCIES Package - -## 🎯 COMPLETE SELF-CONTAINED INSTALLATION - -This package contains EVERYTHING needed to run the Quality Print Service: - -### ✅ What's Included: -- **Embedded Python {PYTHON_VERSION}** - No system Python required! -- **Complete Print Service** - Zero external dependencies -- **Windows Service Installer** - Automatic installation and recovery -- **Chrome Extension** - Web browser integration -- **Comprehensive Documentation** - Installation and usage guides - -### 🚀 INSTALLATION (5 Minutes): - -#### Requirements: -- Windows 10/11 or Windows Server 2016+ -- Administrator privileges (for service installation) -- Google Chrome browser - -#### Step 1: Extract Package -- Extract this ZIP file to any location (Desktop, Downloads, etc.) -- No permanent location needed - installer copies files automatically - -#### Step 2: Install Service -- Right-click `install_service_ZERO_DEPENDENCIES.bat` -- Select "Run as administrator" -- Follow the installation prompts - -#### Step 3: Install Chrome Extension -- Open Chrome browser -- Navigate to `chrome://extensions/` -- Enable "Developer mode" (toggle in top-right) -- Click "Load unpacked" -- Select the `chrome_extension` folder from extracted package - -#### Step 4: Test Installation -- Visit: http://localhost:8765/health -- Should return: {{"status": "healthy", "service": "Windows Print Service"}} - -### 🔧 Technical Details: - -**Service Architecture:** -``` -Quality Web App → Chrome Extension → Windows Service → Printer -``` - -**Printing Methods (automatic fallback):** -1. Adobe Reader (silent printing) -2. SumatraPDF (if Adobe unavailable) -3. PowerShell Print-Document -4. Microsoft Edge (fallback) -5. Windows default printer - -**Service Management:** -- Automatic startup on Windows boot -- Auto-recovery on failure (3 restart attempts) -- Comprehensive logging in: `%USERPROFILE%\\PrintService\\logs\\` - -**Network Configuration:** -- Service runs on: http://localhost:8765 -- Chrome extension communicates via this local endpoint -- No external network access required - -### 📂 Package Contents: -``` -QualityPrintService_COMPLETE_ZERO_DEPENDENCIES.zip -├── python_embedded/ # Python {PYTHON_VERSION} embedded -├── print_service_complete.py # Main service script -├── install_service_ZERO_DEPENDENCIES.bat # Installer -├── chrome_extension/ # Browser extension -│ ├── manifest.json -│ ├── background.js -│ ├── content.js -│ ├── popup.html -│ └── popup.js -└── README.md # This file -``` - -### 🛠️ Troubleshooting: - -**Service Won't Start:** -1. Check Windows Event Viewer → Windows Logs → Application -2. Check service logs in: `%USERPROFILE%\\PrintService\\logs\\` -3. Verify Python embedded installation in: `C:\\QualityPrintService\\` - -**Chrome Extension Not Working:** -1. Verify extension is enabled in `chrome://extensions/` -2. Check browser console for error messages -3. Ensure service is running: http://localhost:8765/health - -**Printing Issues:** -1. Verify printer is installed and accessible -2. Check service logs for printing attempts -3. Test manual PDF printing to verify printer functionality - -### 🔄 Uninstallation: -```cmd -# Stop and remove service -sc stop QualityPrintService -sc delete QualityPrintService - -# Remove installation directory -rmdir /s /q C:\\QualityPrintService - -# Remove Chrome extension manually from chrome://extensions/ -``` - -### 📞 Support: -- Service logs: `%USERPROFILE%\\PrintService\\logs\\service.log` -- Health check: http://localhost:8765/health -- Printer list: http://localhost:8765/printers - ---- -**Package Version:** Complete Zero Dependencies -**Python Version:** {PYTHON_VERSION} (Embedded) -**Created:** {os.path.basename(__file__)} -''' - - zipf.writestr("README_ZERO_DEPENDENCIES.md", readme_content) - files_added += 1 - - print(f"\n📦 Enhanced Package created successfully!") - print(f"📄 Total files: {files_added}") - print(f"📂 Location: {package_path}") - print(f"📏 Size: {package_path.stat().st_size / 1024 / 1024:.1f} MB") - print(f"🔧 Features: Error 1053 fixes, multiple installation methods") - print(f"🚀 Python: {PYTHON_VERSION} embedded (zero dependencies)") - - return True - -if __name__ == "__main__": - print("🚀 Creating Enhanced Package with Error 1053 Fixes...") - print("=" * 65) - - if create_complete_package(): - print("\n✅ SUCCESS: Enhanced package created with Error 1053 fixes!") - print("\n📋 Next steps:") - print("1. Package includes multiple installation methods") - print("2. Error 1053 diagnostic and fix tools included") - print("3. Test on Windows system - should resolve all service issues") - print("4. Update Flask app to serve this enhanced package") - else: - print("\n❌ FAILED: Package creation failed") - sys.exit(1) \ No newline at end of file diff --git a/windows_print_service/fix_error_1053.bat b/windows_print_service/fix_error_1053.bat deleted file mode 100644 index 464e9e4..0000000 --- a/windows_print_service/fix_error_1053.bat +++ /dev/null @@ -1,454 +0,0 @@ -@echo off -REM Windows Service Error 1053 - COMPREHENSIVE DIAGNOSTIC TOOL -REM This script diagnoses and fixes the most common causes of Error 1053 - -setlocal enabledelayedexpansion - -echo ========================================= -echo ERROR 1053 DIAGNOSTIC TOOL -echo Quality Print Service Troubleshooter -echo ========================================= -echo. -echo This tool diagnoses and fixes Windows Service Error 1053: -echo "The service did not respond to the start or control request in a timely fashion" -echo. - -REM Check for administrator privileges -net session >nul 2>&1 -if %errorLevel% neq 0 ( - echo ❌ CRITICAL: Administrator privileges required - echo Right-click this file and select "Run as administrator" - echo. - pause - exit /b 1 -) - -echo ✅ Administrator privileges confirmed -echo. - -REM Set variables -set CURRENT_DIR=%~dp0 -set SERVICE_NAME=QualityPrintService -set INSTALL_DIR=C:\QualityPrintService -set LOG_DIR=%USERPROFILE%\PrintService\logs - -echo =========================================== -echo [STEP 1] SERVICE STATUS DIAGNOSIS -echo =========================================== - -REM Check current service status -echo Checking service status... -sc query "%SERVICE_NAME%" >nul 2>&1 -if %errorLevel% equ 0 ( - echo Service exists - checking status: - sc query "%SERVICE_NAME%" - echo. - - REM Get detailed service info - echo Service configuration: - sc qc "%SERVICE_NAME%" - echo. -) else ( - echo ❌ Service not found - needs installation - echo. -) - -REM Check Task Scheduler -echo Checking Task Scheduler... -schtasks /query /tn "%SERVICE_NAME%" >nul 2>&1 -if %errorLevel% equ 0 ( - echo ✅ Task Scheduler entry found - schtasks /query /tn "%SERVICE_NAME%" /fo LIST - echo. -) else ( - echo ❌ Task Scheduler entry not found - echo. -) - -echo =========================================== -echo [STEP 2] PROCESS AND PORT DIAGNOSIS -echo =========================================== - -REM Check for running processes -echo Checking for existing service processes... -tasklist /fi "imagename eq python.exe" | findstr python.exe >nul 2>&1 -if %errorLevel% equ 0 ( - echo Python processes found: - tasklist /fi "imagename eq python.exe" - echo. -) else ( - echo No Python processes running - echo. -) - -REM Check port 8765 -echo Checking port 8765... -netstat -an | findstr :8765 >nul 2>&1 -if %errorLevel% equ 0 ( - echo ⚠️ Port 8765 is in use: - netstat -an | findstr :8765 - echo. - - REM Find process using port - for /f "tokens=5" %%a in ('netstat -ano ^| findstr :8765') do ( - tasklist /fi "pid eq %%a" 2>nul | findstr /v "INFO:" - ) - echo. -) else ( - echo ✅ Port 8765 is available - echo. -) - -echo =========================================== -echo [STEP 3] PYTHON ENVIRONMENT DIAGNOSIS -echo =========================================== - -REM Check Python installations -echo Checking Python installations... - -REM Check embedded Python -if exist "%INSTALL_DIR%\python_embedded\python.exe" ( - echo ✅ Embedded Python found: %INSTALL_DIR%\python_embedded\python.exe - "%INSTALL_DIR%\python_embedded\python.exe" --version 2>nul - echo. -) else ( - echo ❌ Embedded Python not found at %INSTALL_DIR%\python_embedded\python.exe -) - -if exist "%CURRENT_DIR%python_embedded\python.exe" ( - echo ✅ Installer embedded Python found: %CURRENT_DIR%python_embedded\python.exe - "%CURRENT_DIR%python_embedded\python.exe" --version 2>nul - echo. -) else ( - echo ❌ Installer embedded Python not found -) - -REM Check system Python -python --version >nul 2>&1 -if %errorLevel% equ 0 ( - echo ✅ System Python found: - python --version - where python - echo. -) else ( - echo ❌ System Python not found in PATH - echo. -) - -echo =========================================== -echo [STEP 4] FILE SYSTEM DIAGNOSIS -echo =========================================== - -REM Check installation files -echo Checking installation files... - -if exist "%INSTALL_DIR%" ( - echo ✅ Installation directory exists: %INSTALL_DIR% - echo Contents: - dir "%INSTALL_DIR%" /b - echo. - - if exist "%INSTALL_DIR%\print_service_complete.py" ( - echo ✅ Main service script found - ) else ( - echo ❌ Main service script missing - ) - - if exist "%INSTALL_DIR%\enhanced_service_wrapper.bat" ( - echo ✅ Service wrapper found - ) else ( - echo ❌ Service wrapper missing - ) - -) else ( - echo ❌ Installation directory not found: %INSTALL_DIR% -) - -REM Check log directory -if exist "%LOG_DIR%" ( - echo ✅ Log directory exists: %LOG_DIR% - if exist "%LOG_DIR%\service_wrapper.log" ( - echo Recent log entries: - echo ================== - powershell -Command "Get-Content '%LOG_DIR%\service_wrapper.log' -Tail 10" 2>nul - echo ================== - echo. - ) -) else ( - echo ❌ Log directory not found: %LOG_DIR% - mkdir "%LOG_DIR%" >nul 2>&1 - echo Created log directory -) - -echo =========================================== -echo [STEP 5] SERVICE TEST -echo =========================================== - -REM Determine Python executable -set PYTHON_EXE= -if exist "%INSTALL_DIR%\python_embedded\python.exe" ( - set PYTHON_EXE=%INSTALL_DIR%\python_embedded\python.exe -) else if exist "%CURRENT_DIR%python_embedded\python.exe" ( - set PYTHON_EXE=%CURRENT_DIR%python_embedded\python.exe -) else ( - python --version >nul 2>&1 - if !errorLevel! equ 0 ( - set PYTHON_EXE=python - ) -) - -if "!PYTHON_EXE!"=="" ( - echo ❌ CRITICAL: No Python executable found - echo Cannot perform service test - goto :fixes -) - -echo Testing service with Python: !PYTHON_EXE! - -REM Test service script -if exist "%INSTALL_DIR%\print_service_complete.py" ( - cd /d "%INSTALL_DIR%" - - echo Testing service script syntax... - "!PYTHON_EXE!" -m py_compile print_service_complete.py - if !errorLevel! equ 0 ( - echo ✅ Service script syntax OK - ) else ( - echo ❌ Service script syntax error - ) - - echo Testing service functionality... - "!PYTHON_EXE!" print_service_complete.py --test - if !errorLevel! equ 0 ( - echo ✅ Service test passed - ) else ( - echo ❌ Service test failed - ) - - REM Quick standalone test - echo Testing standalone mode (15 seconds)... - start /min "" "!PYTHON_EXE!" print_service_complete.py --standalone - - timeout /t 5 >nul - - REM Test connection - curl -s http://localhost:8765/health >nul 2>&1 - if !errorLevel! equ 0 ( - echo ✅ Service responding in standalone mode - - REM Stop standalone service - taskkill /f /im python.exe >nul 2>&1 - ) else ( - powershell -Command "try { Invoke-WebRequest -Uri 'http://localhost:8765/health' -UseBasicParsing } catch { exit 1 }" >nul 2>&1 - if !errorLevel! equ 0 ( - echo ✅ Service responding in standalone mode - taskkill /f /im python.exe >nul 2>&1 - ) else ( - echo ❌ Service not responding in standalone mode - taskkill /f /im python.exe >nul 2>&1 - ) - ) -) else ( - echo ❌ Service script not found at %INSTALL_DIR%\print_service_complete.py -) - -echo. - -:fixes -echo =========================================== -echo [STEP 6] AUTOMATED FIXES FOR ERROR 1053 -echo =========================================== - -echo Applying automated fixes... - -REM Fix 1: Stop conflicting services -echo [FIX 1] Stopping any conflicting services... -net stop "%SERVICE_NAME%" >nul 2>&1 -schtasks /end /tn "%SERVICE_NAME%" >nul 2>&1 -taskkill /f /im python.exe >nul 2>&1 -timeout /t 3 >nul -echo ✅ Services stopped - -REM Fix 2: Remove old service entries -echo [FIX 2] Cleaning old service entries... -sc delete "%SERVICE_NAME%" >nul 2>&1 -schtasks /delete /tn "%SERVICE_NAME%" /f >nul 2>&1 -echo ✅ Old entries removed - -REM Fix 3: Create enhanced service wrapper with timeout handling -echo [FIX 3] Creating enhanced service wrapper... - -set ENHANCED_WRAPPER=%INSTALL_DIR%\error_1053_fix_wrapper.bat - -mkdir "%INSTALL_DIR%" >nul 2>&1 - -echo @echo off > "%ENHANCED_WRAPPER%" -echo REM Enhanced Windows Service Wrapper - Error 1053 Fix >> "%ENHANCED_WRAPPER%" -echo REM This wrapper includes specific fixes for SCM timeout issues >> "%ENHANCED_WRAPPER%" -echo. >> "%ENHANCED_WRAPPER%" -echo setlocal >> "%ENHANCED_WRAPPER%" -echo. >> "%ENHANCED_WRAPPER%" -echo REM Logging >> "%ENHANCED_WRAPPER%" -echo set LOG_FILE=%LOG_DIR%\error_1053_fix.log >> "%ENHANCED_WRAPPER%" -echo echo %%date%% %%time%% - Service wrapper starting... ^>^> "%%LOG_FILE%%" >> "%ENHANCED_WRAPPER%" -echo. >> "%ENHANCED_WRAPPER%" -echo REM Change to service directory >> "%ENHANCED_WRAPPER%" -echo cd /d "%INSTALL_DIR%" >> "%ENHANCED_WRAPPER%" -echo. >> "%ENHANCED_WRAPPER%" -echo REM Pre-flight checks >> "%ENHANCED_WRAPPER%" -if "!PYTHON_EXE!" neq "" ( - echo if not exist "!PYTHON_EXE!" ( >> "%ENHANCED_WRAPPER%" - echo echo ERROR: Python not found at !PYTHON_EXE! ^>^> "%%LOG_FILE%%" >> "%ENHANCED_WRAPPER%" - echo exit /b 1 >> "%ENHANCED_WRAPPER%" - echo ^) >> "%ENHANCED_WRAPPER%" -) -echo. >> "%ENHANCED_WRAPPER%" -echo if not exist "print_service_complete.py" ( >> "%ENHANCED_WRAPPER%" -echo echo ERROR: Service script not found ^>^> "%%LOG_FILE%%" >> "%ENHANCED_WRAPPER%" -echo exit /b 1 >> "%ENHANCED_WRAPPER%" -echo ^) >> "%ENHANCED_WRAPPER%" -echo. >> "%ENHANCED_WRAPPER%" -echo REM Quick response to SCM - Start service immediately in background >> "%ENHANCED_WRAPPER%" -echo echo Service responding to SCM... ^>^> "%%LOG_FILE%%" >> "%ENHANCED_WRAPPER%" -echo. >> "%ENHANCED_WRAPPER%" -echo REM Start the actual service process >> "%ENHANCED_WRAPPER%" -if "!PYTHON_EXE!" neq "" ( - echo start /b "Quality Print Service" "!PYTHON_EXE!" "print_service_complete.py" --service >> "%ENHANCED_WRAPPER%" -) else ( - echo start /b "Quality Print Service" python "print_service_complete.py" --service >> "%ENHANCED_WRAPPER%" -) -echo. >> "%ENHANCED_WRAPPER%" -echo REM Keep wrapper alive briefly to satisfy SCM >> "%ENHANCED_WRAPPER%" -echo timeout /t 2 /nobreak ^>nul >> "%ENHANCED_WRAPPER%" -echo. >> "%ENHANCED_WRAPPER%" -echo echo Service started successfully ^>^> "%%LOG_FILE%%" >> "%ENHANCED_WRAPPER%" -echo exit /b 0 >> "%ENHANCED_WRAPPER%" - -echo ✅ Enhanced wrapper created - -REM Fix 4: Install service with proper timeout settings -echo [FIX 4] Installing service with Error 1053 fixes... - -REM Create service with extended timeout -sc create "%SERVICE_NAME%" binPath= "\"%ENHANCED_WRAPPER%\"" DisplayName= "Quality Print Service (Error 1053 Fixed)" start= auto >nul 2>&1 - -if %errorLevel% equ 0 ( - echo ✅ Service created successfully - - REM Configure service for Error 1053 prevention - echo Configuring service recovery... - sc failure "%SERVICE_NAME%" reset= 86400 actions= restart/5000/restart/5000/restart/5000 >nul 2>&1 - - REM Set service to auto-start with delay - sc config "%SERVICE_NAME%" start= delayed-auto >nul 2>&1 - - echo ✅ Service configured with Error 1053 fixes -) else ( - echo ❌ Service creation failed -) - -echo. - -echo =========================================== -echo [STEP 7] SERVICE START TEST -echo =========================================== - -echo Testing service start with Error 1053 fixes... - -REM Start service -net start "%SERVICE_NAME%" 2>&1 -if %errorLevel% equ 0 ( - echo ✅ SERVICE STARTED SUCCESSFULLY! - echo Error 1053 has been FIXED! 🎉 - - REM Wait and test connection - echo Waiting for service to initialize... - timeout /t 10 >nul - - echo Testing service connection... - curl -s http://localhost:8765/health >nul 2>&1 - if !errorLevel! equ 0 ( - echo ✅ Service is responding properly - echo. - echo ======================================== - echo PROBLEM SOLVED! 🎉 - echo ======================================== - echo. - echo ✅ Windows Service Error 1053 FIXED - echo ✅ Service: %SERVICE_NAME% - echo ✅ Status: Running and responding - echo ✅ URL: http://localhost:8765 - echo. - goto :success - ) else ( - powershell -Command "try { Invoke-WebRequest -Uri 'http://localhost:8765/health' -UseBasicParsing } catch { exit 1 }" >nul 2>&1 - if !errorLevel! equ 0 ( - echo ✅ Service is responding properly - goto :success - ) else ( - echo ⚠️ Service started but not responding - echo Check logs: %LOG_DIR%\error_1053_fix.log - ) - ) -) else ( - echo ❌ Service start failed - Error 1053 may persist - echo. - echo =========================================== - echo [ALTERNATIVE SOLUTIONS] - echo =========================================== - echo. - echo Since SC Service failed, trying alternative methods... - - REM Alternative: Task Scheduler - echo Installing via Task Scheduler... - schtasks /create /tn "%SERVICE_NAME%" /tr "\"%ENHANCED_WRAPPER%\"" /sc onstart /ru SYSTEM /rl HIGHEST >nul 2>&1 - if !errorLevel! equ 0 ( - echo ✅ Task Scheduler service created - schtasks /run /tn "%SERVICE_NAME%" >nul 2>&1 - if !errorLevel! equ 0 ( - echo ✅ Task Scheduler service started - echo Alternative solution: Task Scheduler - ) - ) - - REM Alternative: Manual startup - echo. - echo Manual startup option: - echo Run this command to start manually: - echo "%ENHANCED_WRAPPER%" -) - -:success -echo. -echo =========================================== -echo [STEP 8] SUMMARY AND RECOMMENDATIONS -echo =========================================== - -echo Diagnostic complete! -echo. -echo 📋 TROUBLESHOOTING SUMMARY: -echo ✅ Administrator privileges: OK -echo ✅ Enhanced service wrapper: Created -echo ✅ Error 1053 fixes: Applied -echo ✅ Service configuration: Updated -echo. - -if exist "%LOG_DIR%\error_1053_fix.log" ( - echo 📊 Recent service logs: - echo ======================== - powershell -Command "Get-Content '%LOG_DIR%\error_1053_fix.log' -Tail 5" 2>nul - echo ======================== - echo. -) - -echo 🔧 Service Management Commands: -echo - Start: net start %SERVICE_NAME% -echo - Stop: net stop %SERVICE_NAME% -echo - Status: sc query %SERVICE_NAME% -echo. -echo 📁 Log files: %LOG_DIR% -echo 🌐 Service URL: http://localhost:8765 -echo 🔍 Health check: http://localhost:8765/health -echo. -echo Press any key to exit... -pause >nul \ No newline at end of file diff --git a/windows_print_service/install_service_ENHANCED.bat b/windows_print_service/install_service_ENHANCED.bat deleted file mode 100644 index 92aac2e..0000000 --- a/windows_print_service/install_service_ENHANCED.bat +++ /dev/null @@ -1,407 +0,0 @@ -@echo off -REM Windows Print Service - ENHANCED INSTALLER - Fixes Error 1053 -REM This installer addresses the most common causes of Windows Service startup failures - -setlocal enabledelayedexpansion - -echo ========================================= -echo Quality Print Service - ENHANCED INSTALLER -echo Fixes Windows Service Error 1053 -echo ========================================= -echo. -echo This installer includes multiple methods to ensure service starts: -echo ✅ Windows SC Service (preferred) -echo ✅ Task Scheduler Service (fallback) -echo ✅ Startup Script (manual fallback) -echo ✅ Enhanced error detection and recovery -echo. - -REM Check for administrator privileges -net session >nul 2>&1 -if %errorLevel% neq 0 ( - echo ❌ ERROR: Administrator privileges required - echo Please right-click this file and select "Run as administrator" - echo. - pause - exit /b 1 -) - -echo [1/8] Administrator privileges confirmed ✅ -echo. - -REM Set variables -set CURRENT_DIR=%~dp0 -set SERVICE_NAME=QualityPrintService -set SERVICE_DISPLAY_NAME=Quality Print Service -set INSTALL_DIR=C:\QualityPrintService -set LOG_DIR=%USERPROFILE%\PrintService\logs - -REM Detect Python executable -echo [2/8] Detecting Python installation... - -set PYTHON_EXE= -set PYTHON_SCRIPT=%INSTALL_DIR%\print_service_complete.py - -REM Check for embedded Python first -if exist "%INSTALL_DIR%\python_embedded\python.exe" ( - set PYTHON_EXE=%INSTALL_DIR%\python_embedded\python.exe - echo Found embedded Python: !PYTHON_EXE! ✅ -) else if exist "%CURRENT_DIR%python_embedded\python.exe" ( - set PYTHON_EXE=%CURRENT_DIR%python_embedded\python.exe - echo Found embedded Python in installer: !PYTHON_EXE! ✅ -) else ( - REM Check system Python - python --version >nul 2>&1 - if !errorLevel! equ 0 ( - set PYTHON_EXE=python - echo Found system Python ✅ - ) else ( - echo ❌ ERROR: Python not found - echo Please ensure Python 3.7+ is installed or use the zero-dependency package - pause - exit /b 1 - ) -) - -echo. - -REM Stop existing service -echo [3/8] Stopping existing service (if any)... -sc query "%SERVICE_NAME%" >nul 2>&1 -if %errorLevel% equ 0 ( - echo Stopping existing service... - net stop "%SERVICE_NAME%" >nul 2>&1 - sc delete "%SERVICE_NAME%" >nul 2>&1 - timeout /t 3 >nul -) - -REM Stop any existing task -schtasks /end /tn "%SERVICE_NAME%" >nul 2>&1 -schtasks /delete /tn "%SERVICE_NAME%" /f >nul 2>&1 - -echo Service cleanup completed ✅ -echo. - -REM Create installation directory -echo [4/8] Creating installation directory... -if exist "%INSTALL_DIR%" ( - echo Removing old installation... - rmdir /s /q "%INSTALL_DIR%" >nul 2>&1 -) -mkdir "%INSTALL_DIR%" >nul 2>&1 - -REM Create log directory -mkdir "%LOG_DIR%" >nul 2>&1 - -echo Installation directory: %INSTALL_DIR% ✅ -echo Log directory: %LOG_DIR% ✅ -echo. - -REM Copy service files -echo [5/8] Installing service files... - -REM Copy Python embedded if available -if exist "%CURRENT_DIR%python_embedded\" ( - echo Copying embedded Python distribution... - xcopy "%CURRENT_DIR%python_embedded" "%INSTALL_DIR%\python_embedded\" /E /I /Y >nul - set PYTHON_EXE=%INSTALL_DIR%\python_embedded\python.exe - echo Embedded Python installed ✅ -) - -REM Copy service scripts -copy "%CURRENT_DIR%print_service_complete.py" "%INSTALL_DIR%\" >nul -copy "%CURRENT_DIR%service_wrapper.py" "%INSTALL_DIR%\" >nul 2>&1 -copy "%CURRENT_DIR%service_installer.py" "%INSTALL_DIR%\" >nul 2>&1 - -echo Service files installed ✅ -echo. - -REM Test service before installing -echo [6/8] Testing service functionality... -cd /d "%INSTALL_DIR%" - -echo Testing Python and service script... -"%PYTHON_EXE%" "%PYTHON_SCRIPT%" --test >nul 2>&1 -if %errorLevel% equ 0 ( - echo Service test passed ✅ -) else ( - echo ⚠️ Service test failed - continuing with installation -) - -REM Check port availability -echo Testing port 8765 availability... -netstat -an | findstr :8765 >nul 2>&1 -if %errorLevel% equ 0 ( - echo ⚠️ Port 8765 is in use - service may conflict -) else ( - echo Port 8765 available ✅ -) -echo. - -REM Install service - Multiple methods -echo [7/8] Installing Windows service with multiple fallback methods... - -REM Create enhanced service wrapper -set WRAPPER_BAT=%INSTALL_DIR%\enhanced_service_wrapper.bat - -echo @echo off > "%WRAPPER_BAT%" -echo REM Enhanced Windows Service Wrapper - Error 1053 Fix >> "%WRAPPER_BAT%" -echo cd /d "%INSTALL_DIR%" >> "%WRAPPER_BAT%" -echo. >> "%WRAPPER_BAT%" -echo REM Log service start attempt >> "%WRAPPER_BAT%" -echo echo %%date%% %%time%% - Service wrapper starting... ^>^> "%LOG_DIR%\service_wrapper.log" >> "%WRAPPER_BAT%" -echo. >> "%WRAPPER_BAT%" -echo REM Verify files exist >> "%WRAPPER_BAT%" -echo if not exist "%PYTHON_EXE%" ( >> "%WRAPPER_BAT%" -echo echo ERROR: Python not found at %PYTHON_EXE% ^>^> "%LOG_DIR%\service_wrapper.log" >> "%WRAPPER_BAT%" -echo exit /b 1 >> "%WRAPPER_BAT%" -echo ^) >> "%WRAPPER_BAT%" -echo. >> "%WRAPPER_BAT%" -echo if not exist "%PYTHON_SCRIPT%" ( >> "%WRAPPER_BAT%" -echo echo ERROR: Service script not found ^>^> "%LOG_DIR%\service_wrapper.log" >> "%WRAPPER_BAT%" -echo exit /b 1 >> "%WRAPPER_BAT%" -echo ^) >> "%WRAPPER_BAT%" -echo. >> "%WRAPPER_BAT%" -echo REM Start service with error handling >> "%WRAPPER_BAT%" -echo echo Starting service process... ^>^> "%LOG_DIR%\service_wrapper.log" >> "%WRAPPER_BAT%" -echo "%PYTHON_EXE%" "%PYTHON_SCRIPT%" --service >> "%WRAPPER_BAT%" -echo. >> "%WRAPPER_BAT%" -echo REM Log exit code >> "%WRAPPER_BAT%" -echo echo Service exited with code %%errorlevel%% ^>^> "%LOG_DIR%\service_wrapper.log" >> "%WRAPPER_BAT%" - -REM Method 1: Windows SC Service -echo Installing as Windows SC Service... -sc create "%SERVICE_NAME%" binPath= "\"%WRAPPER_BAT%\"" DisplayName= "%SERVICE_DISPLAY_NAME%" start= auto >nul 2>&1 - -if %errorLevel% equ 0 ( - echo Windows SC Service created ✅ - - REM Configure recovery - sc failure "%SERVICE_NAME%" reset= 86400 actions= restart/5000/restart/5000/restart/5000 >nul 2>&1 - - REM Try to start service - echo Starting SC service... - net start "%SERVICE_NAME%" >nul 2>&1 - if !errorLevel! equ 0 ( - echo SC Service started successfully ✅ - set SERVICE_METHOD=SC_SERVICE - goto :service_installed - ) else ( - echo ⚠️ SC Service created but failed to start - trying Task Scheduler... - ) -) else ( - echo ❌ SC Service creation failed - trying Task Scheduler... -) - -REM Method 2: Task Scheduler Service -echo Installing as Task Scheduler Service... - -REM Create task XML -set TASK_XML=%INSTALL_DIR%\%SERVICE_NAME%_task.xml - -echo ^ > "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^Quality Print Service - Automatic Label Printing^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^true^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^S-1-5-18^ >> "%TASK_XML%" -echo ^HighestAvailable^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^IgnoreNew^ >> "%TASK_XML%" -echo ^false^ >> "%TASK_XML%" -echo ^false^ >> "%TASK_XML%" -echo ^true^ >> "%TASK_XML%" -echo ^true^ >> "%TASK_XML%" -echo ^false^ >> "%TASK_XML%" -echo ^true^ >> "%TASK_XML%" -echo ^true^ >> "%TASK_XML%" -echo ^false^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^PT5M^ >> "%TASK_XML%" -echo ^3^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^"%PYTHON_EXE%"^ >> "%TASK_XML%" -echo ^"%PYTHON_SCRIPT%" --service^ >> "%TASK_XML%" -echo ^%INSTALL_DIR%^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" -echo ^ >> "%TASK_XML%" - -schtasks /create /tn "%SERVICE_NAME%" /xml "%TASK_XML%" >nul 2>&1 -if %errorLevel% equ 0 ( - echo Task Scheduler service created ✅ - - REM Start task - schtasks /run /tn "%SERVICE_NAME%" >nul 2>&1 - if !errorLevel! equ 0 ( - echo Task Scheduler service started ✅ - set SERVICE_METHOD=TASK_SCHEDULER - goto :service_installed - ) else ( - echo ⚠️ Task created but failed to start - ) -) else ( - echo ❌ Task Scheduler creation failed -) - -REM Method 3: Startup Script Fallback -echo Installing as Startup Script... -set STARTUP_DIR=%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup -set STARTUP_SCRIPT=%STARTUP_DIR%\QualityPrintService.bat - -echo @echo off > "%STARTUP_SCRIPT%" -echo REM Quality Print Service - Startup Script >> "%STARTUP_SCRIPT%" -echo cd /d "%INSTALL_DIR%" >> "%STARTUP_SCRIPT%" -echo start /min "Quality Print Service" "%PYTHON_EXE%" "%PYTHON_SCRIPT%" --service >> "%STARTUP_SCRIPT%" - -if exist "%STARTUP_SCRIPT%" ( - echo Startup script created ✅ - - REM Start immediately - start /min "" "%STARTUP_SCRIPT%" - echo Service started via startup script ✅ - set SERVICE_METHOD=STARTUP_SCRIPT - goto :service_installed -) - -REM If we get here, all methods failed -echo ❌ All installation methods failed -goto :installation_failed - -:service_installed -echo. - -REM Verification -echo [8/8] Verifying installation... - -echo Waiting for service to start... -timeout /t 5 >nul - -REM Test service connection -echo Testing service connection... -for /L %%i in (1,1,10) do ( - curl -s http://localhost:8765/health >nul 2>&1 - if !errorLevel! equ 0 ( - echo Service is responding ✅ - goto :success - ) - - powershell -Command "try { Invoke-WebRequest -Uri 'http://localhost:8765/health' -UseBasicParsing } catch { exit 1 }" >nul 2>&1 - if !errorLevel! equ 0 ( - echo Service is responding ✅ - goto :success - ) - - echo Attempt %%i failed, retrying... - timeout /t 2 >nul -) - -echo ⚠️ Service installed but not responding -goto :partial_success - -:success -echo. -echo ======================================== -echo INSTALLATION SUCCESSFUL! 🎉 -echo ======================================== -echo. -echo ✅ Service Method: !SERVICE_METHOD! -echo ✅ Service URL: http://localhost:8765 -echo ✅ Health Check: http://localhost:8765/health -echo ✅ Service will start automatically on boot -echo. -echo 📋 NEXT STEPS: -echo 1. Install Chrome extension from 'chrome_extension' folder -echo 2. Test printing from the web application -echo 3. Configure printer settings if needed -echo. -echo 📊 Service Management: -if "!SERVICE_METHOD!"=="SC_SERVICE" ( - echo - Start: net start %SERVICE_NAME% - echo - Stop: net stop %SERVICE_NAME% - echo - Status: sc query %SERVICE_NAME% -) else if "!SERVICE_METHOD!"=="TASK_SCHEDULER" ( - echo - Start: schtasks /run /tn %SERVICE_NAME% - echo - Stop: schtasks /end /tn %SERVICE_NAME% - echo - Status: schtasks /query /tn %SERVICE_NAME% -) else ( - echo - Start: Run startup script manually - echo - Stop: End process in Task Manager -) -echo. -echo 📁 Logs: %LOG_DIR% -echo. -goto :end - -:partial_success -echo. -echo ======================================== -echo INSTALLATION COMPLETED -echo ======================================== -echo. -echo ⚠️ Service installed but verification failed -echo 📋 Manual verification steps: -echo. -echo 1. Check if service is running: -if "!SERVICE_METHOD!"=="SC_SERVICE" ( - echo sc query %SERVICE_NAME% -) else if "!SERVICE_METHOD!"=="TASK_SCHEDULER" ( - echo schtasks /query /tn %SERVICE_NAME% -) else ( - echo Check Task Manager for python.exe process -) -echo. -echo 2. Test service manually: -echo http://localhost:8765/health -echo. -echo 3. Check logs: -echo %LOG_DIR%\service_wrapper.log -echo. -echo 4. Manual start if needed: -if "!SERVICE_METHOD!"=="SC_SERVICE" ( - echo net start %SERVICE_NAME% -) else if "!SERVICE_METHOD!"=="TASK_SCHEDULER" ( - echo schtasks /run /tn %SERVICE_NAME% -) else ( - echo Run: %STARTUP_SCRIPT% -) -echo. -goto :end - -:installation_failed -echo. -echo ======================================== -echo INSTALLATION FAILED -echo ======================================== -echo. -echo ❌ All service installation methods failed -echo. -echo 📋 Troubleshooting steps: -echo 1. Verify Administrator privileges -echo 2. Check Python installation -echo 3. Ensure port 8765 is available -echo 4. Review logs in: %LOG_DIR% -echo 5. Try manual service start -echo. -echo 🔧 Manual installation: -echo cd /d "%INSTALL_DIR%" -echo "%PYTHON_EXE%" "%PYTHON_SCRIPT%" --standalone -echo. -pause -exit /b 1 - -:end -echo Press any key to exit... -pause >nul \ No newline at end of file diff --git a/windows_print_service/install_service_complete.bat b/windows_print_service/install_service_complete.bat deleted file mode 100644 index 57b1941..0000000 --- a/windows_print_service/install_service_complete.bat +++ /dev/null @@ -1,243 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -echo ======================================== -echo Quality Label Print Service Installer -echo Complete Self-Contained Version -echo ======================================== -echo. - -REM Check for administrator privileges -net session >nul 2>&1 -if %errorLevel% neq 0 ( - echo ERROR: This installer requires Administrator privileges. - echo Please right-click this file and select "Run as administrator" - echo. - pause - exit /b 1 -) - -echo [1/6] Administrator privileges confirmed ✓ -echo. - -REM Get current directory and set variables -set CURRENT_DIR=%~dp0 -set SERVICE_NAME=QualityPrintService -set SERVICE_DISPLAY_NAME=Quality Label Print Service -set INSTALL_DIR=C:\QualityPrintService -set PYTHON_SCRIPT=%INSTALL_DIR%\print_service_complete.py -set LOG_DIR=%USERPROFILE%\PrintService\logs - -echo [2/6] Checking Python installation... - -REM Check if Python is available -python --version >nul 2>&1 -if %errorLevel% neq 0 ( - echo WARNING: Python not found in PATH - echo. - echo Installing portable Python interpreter... - - REM Download portable Python (this would need to be included in the zip) - if exist "%CURRENT_DIR%python_portable" ( - echo Using included portable Python ✓ - set PYTHON_EXE=%CURRENT_DIR%python_portable\python.exe - ) else ( - echo ERROR: Portable Python not found in package - echo Please ensure python_portable folder is included - pause - exit /b 1 - ) -) else ( - echo Python found in system PATH ✓ - set PYTHON_EXE=python -) - -echo [3/6] Creating installation directories... - -REM Create installation directory -if not exist "%INSTALL_DIR%" ( - mkdir "%INSTALL_DIR%" - echo Created: %INSTALL_DIR% ✓ -) - -REM Create log directory -if not exist "%LOG_DIR%" ( - mkdir "%LOG_DIR%" - echo Created: %LOG_DIR% ✓ -) - -echo [4/6] Installing service files... - -REM Copy service files -copy "%CURRENT_DIR%print_service_complete.py" "%INSTALL_DIR%\" >nul -if %errorLevel% equ 0 ( - echo Copied print service script ✓ -) else ( - echo ERROR: Failed to copy service script - pause - exit /b 1 -) - -REM Copy additional files if they exist -if exist "%CURRENT_DIR%requirements_complete.txt" ( - copy "%CURRENT_DIR%requirements_complete.txt" "%INSTALL_DIR%\" >nul - echo Copied requirements file ✓ -) - -REM Copy portable Python if included -if exist "%CURRENT_DIR%python_portable" ( - echo Copying portable Python interpreter... - xcopy "%CURRENT_DIR%python_portable" "%INSTALL_DIR%\python_portable\" /E /I /H /Y >nul - if %errorLevel% equ 0 ( - echo Portable Python installed ✓ - set PYTHON_EXE=%INSTALL_DIR%\python_portable\python.exe - ) -) - -echo [5/6] Installing Windows service... - -REM Remove existing service if it exists -sc query "%SERVICE_NAME%" >nul 2>&1 -if %errorLevel% equ 0 ( - echo Stopping existing service... - sc stop "%SERVICE_NAME%" >nul 2>&1 - timeout /t 3 >nul - echo Removing existing service... - sc delete "%SERVICE_NAME%" >nul 2>&1 - timeout /t 2 >nul -) - -REM Try to install with NSSM first (if available) -if exist "%CURRENT_DIR%nssm.exe" ( - echo Installing with NSSM (Non-Sucking Service Manager)... - - "%CURRENT_DIR%nssm.exe" install "%SERVICE_NAME%" "%PYTHON_EXE%" "%PYTHON_SCRIPT%" - "%CURRENT_DIR%nssm.exe" set "%SERVICE_NAME%" DisplayName "%SERVICE_DISPLAY_NAME%" - "%CURRENT_DIR%nssm.exe" set "%SERVICE_NAME%" Description "Quality Label Printing Service for Windows" - "%CURRENT_DIR%nssm.exe" set "%SERVICE_NAME%" Start SERVICE_AUTO_START - "%CURRENT_DIR%nssm.exe" set "%SERVICE_NAME%" AppStdout "%LOG_DIR%\service_output.log" - "%CURRENT_DIR%nssm.exe" set "%SERVICE_NAME%" AppStderr "%LOG_DIR%\service_error.log" - "%CURRENT_DIR%nssm.exe" set "%SERVICE_NAME%" AppRotateFiles 1 - "%CURRENT_DIR%nssm.exe" set "%SERVICE_NAME%" AppRotateOnline 1 - "%CURRENT_DIR%nssm.exe" set "%SERVICE_NAME%" AppRotateBytes 1048576 - - echo Windows service installed with NSSM ✓ - -) else ( - echo Installing with Windows SC command (Enhanced Service Wrapper)... - - REM Copy service wrapper - copy "%CURRENT_DIR%service_wrapper.py" "%INSTALL_DIR%\" >nul - if %errorLevel% neq 0 ( - echo WARNING: Service wrapper not found, creating basic wrapper... - ) - - REM Create enhanced service wrapper batch file - set WRAPPER_BAT=%INSTALL_DIR%\service_wrapper.bat - - echo @echo off > "%WRAPPER_BAT%" - echo REM Windows Print Service Wrapper - Fixed for Error 1053 >> "%WRAPPER_BAT%" - echo cd /d "%INSTALL_DIR%" >> "%WRAPPER_BAT%" - echo. >> "%WRAPPER_BAT%" - echo REM Check if Python service wrapper exists >> "%WRAPPER_BAT%" - echo if exist "%INSTALL_DIR%\service_wrapper.py" ( >> "%WRAPPER_BAT%" - echo echo Starting service with wrapper... >> "%WRAPPER_BAT%" - echo "%PYTHON_EXE%" "%INSTALL_DIR%\service_wrapper.py" >> "%WRAPPER_BAT%" - echo ^) else ( >> "%WRAPPER_BAT%" - echo echo Starting service directly... >> "%WRAPPER_BAT%" - echo "%PYTHON_EXE%" "%PYTHON_SCRIPT%" --service >> "%WRAPPER_BAT%" - echo ^) >> "%WRAPPER_BAT%" - - REM Install service using sc command with enhanced wrapper - sc create "%SERVICE_NAME%" binPath= "\"%WRAPPER_BAT%\"" DisplayName= "%SERVICE_DISPLAY_NAME%" start= auto - - if %errorLevel% equ 0 ( - echo Windows service installed with Enhanced SC Wrapper ✓ - ) else ( - echo ERROR: Failed to install Windows service - echo Trying scheduled task fallback... - goto :install_scheduled_task - ) -) - -REM Configure service recovery options -echo Configuring service recovery options... -sc failure "%SERVICE_NAME%" reset= 86400 actions= restart/5000/restart/5000/restart/5000 >nul 2>&1 - -goto :start_service - -:install_scheduled_task -echo [5/6] Installing as scheduled task (fallback)... - -REM Create scheduled task as fallback -schtasks /create /tn "%SERVICE_NAME%" /tr "\"%PYTHON_EXE%\" \"%PYTHON_SCRIPT%\"" /sc onstart /ru SYSTEM /f >nul 2>&1 - -if %errorLevel% equ 0 ( - echo Scheduled task installed ✓ - - REM Start the task - schtasks /run /tn "%SERVICE_NAME%" >nul 2>&1 - echo Scheduled task started ✓ -) else ( - echo ERROR: Failed to install scheduled task - pause - exit /b 1 -) - -goto :install_chrome_extension - -:start_service -echo [6/6] Starting service... - -REM Start the service -sc start "%SERVICE_NAME%" >nul 2>&1 - -if %errorLevel% equ 0 ( - echo Service started successfully ✓ -) else ( - echo WARNING: Service may not have started properly - echo This is normal on first install - the service will auto-start on next boot -) - -:install_chrome_extension -echo. -echo ======================================== -echo Installation Complete! ✓ -echo ======================================== -echo. -echo Service Details: -echo Name: %SERVICE_NAME% -echo Location: %INSTALL_DIR% -echo Logs: %LOG_DIR% -echo URL: http://localhost:8765 -echo. - -REM Test service connectivity -echo Testing service connectivity... -timeout /t 3 >nul - -powershell -Command "try { $response = Invoke-RestMethod -Uri 'http://localhost:8765/health' -TimeoutSec 10; if ($response.status -eq 'healthy') { Write-Host 'Service is responding ✓' -ForegroundColor Green } else { Write-Host 'Service responded but may have issues' -ForegroundColor Yellow } } catch { Write-Host 'Service not yet responding (this is normal on first install)' -ForegroundColor Yellow }" - -echo. -echo Next Steps: -echo 1. Install Chrome Extension: -echo - Open Chrome and go to chrome://extensions/ -echo - Enable 'Developer mode' -echo - Click 'Load unpacked' and select the chrome_extension folder -echo. -echo 2. Test the installation: -echo - Visit: http://localhost:8765/health -echo - Expected response: {"status": "healthy"} -echo. -echo 3. The service will automatically start with Windows -echo. - -if exist "%CURRENT_DIR%chrome_extension\" ( - echo Opening Chrome extension folder... - explorer "%CURRENT_DIR%chrome_extension" -) - -echo Installation completed successfully! -echo The Quality Print Service is now ready to use. -echo. -pause \ No newline at end of file diff --git a/windows_print_service/print_service.py b/windows_print_service/print_service.py deleted file mode 100644 index 2e8b948..0000000 --- a/windows_print_service/print_service.py +++ /dev/null @@ -1,666 +0,0 @@ -""" -Windows Print Service for Quality Label Printing -Receives PDFs from Chrome extension and prints them page by page - -Windows-compatible version with comprehensive dependency support -""" - -import os -import sys -import json -import logging -import tempfile -import subprocess -import platform -from http.server import HTTPServer, BaseHTTPRequestHandler -from urllib.parse import urlparse, parse_qs -import urllib.request -from datetime import datetime -import threading -import time -import shutil -import winreg -from pathlib import Path - -# Windows-specific imports with fallbacks -try: - import win32print - import win32api - import win32con - import win32ui - import win32gui - WINDOWS_PRINTING_AVAILABLE = True -except ImportError: - print("Warning: pywin32 not available. Some Windows-specific features may not work.") - WINDOWS_PRINTING_AVAILABLE = False - -# PDF processing imports with fallbacks -try: - from PyPDF2 import PdfReader, PdfWriter - PYPDF2_AVAILABLE = True -except ImportError: - try: - from pypdf import PdfReader, PdfWriter - PYPDF2_AVAILABLE = True - except ImportError: - print("Warning: PDF processing library not available. Install PyPDF2 or pypdf.") - PYPDF2_AVAILABLE = False - -# Advanced PDF processing (optional) -try: - import fitz # PyMuPDF - PYMUPDF_AVAILABLE = True -except ImportError: - PYMUPDF_AVAILABLE = False - -# Image processing for PDF conversion -try: - from PIL import Image - from pdf2image import convert_from_path - IMAGE_PROCESSING_AVAILABLE = True -except ImportError: - IMAGE_PROCESSING_AVAILABLE = False - -# HTTP requests -try: - import requests - REQUESTS_AVAILABLE = True -except ImportError: - REQUESTS_AVAILABLE = False - -# Configure logging -log_dir = os.path.join(os.path.expanduser("~"), "QualityLabelPrinting", "logs") -os.makedirs(log_dir, exist_ok=True) -log_file = os.path.join(log_dir, "print_service.log") - -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(levelname)s - %(message)s', - handlers=[ - logging.FileHandler(log_file), - logging.StreamHandler(sys.stdout) - ] -) - -logger = logging.getLogger(__name__) - -class PrintServiceHandler(BaseHTTPRequestHandler): - def log_message(self, format, *args): - """Override to use our logger instead of stderr""" - logger.info(f"{self.address_string()} - {format % args}") - - def do_GET(self): - """Handle GET requests""" - try: - parsed_path = urlparse(self.path) - path = parsed_path.path - - if path == '/health': - self.handle_health_check() - elif path == '/printers': - self.handle_get_printers() - elif path == '/status': - self.handle_service_status() - else: - self.send_error(404, "Endpoint not found") - - except Exception as e: - logger.error(f"Error handling GET request: {e}") - self.send_error(500, str(e)) - - def do_POST(self): - """Handle POST requests""" - try: - parsed_path = urlparse(self.path) - path = parsed_path.path - - if path == '/print_pdf': - self.handle_print_pdf() - elif path == '/print_url': - self.handle_print_url() - else: - self.send_error(404, "Endpoint not found") - - except Exception as e: - logger.error(f"Error handling POST request: {e}") - self.send_error(500, str(e)) - - def handle_health_check(self): - """Health check endpoint""" - response = { - "status": "healthy", - "service": "Quality Label Print Service", - "version": "2.0.0", - "platform": "Windows", - "timestamp": datetime.now().isoformat(), - "capabilities": ["pdf_printing", "page_by_page", "printer_selection"] - } - - self.send_json_response(200, response) - - def handle_get_printers(self): - """Get available printers""" - try: - printers = self.get_available_printers() - response = { - "success": True, - "printers": printers, - "count": len(printers) - } - self.send_json_response(200, response) - - except Exception as e: - logger.error(f"Error getting printers: {e}") - response = { - "success": False, - "error": str(e), - "printers": [] - } - self.send_json_response(500, response) - - def handle_service_status(self): - """Service status information""" - response = { - "service_name": "Quality Label Print Service", - "running": True, - "uptime": "Available", - "last_print_job": getattr(self.server, 'last_print_time', 'Never'), - "total_jobs": getattr(self.server, 'total_jobs', 0) - } - self.send_json_response(200, response) - - def handle_print_pdf(self): - """Handle PDF printing requests""" - try: - content_length = int(self.headers['Content-Length']) - post_data = self.rfile.read(content_length) - data = json.loads(post_data.decode('utf-8')) - - logger.info(f"Received print request: {data}") - - # Extract request data - pdf_url = data.get('pdf_url') - printer_name = data.get('printer_name', 'default') - order_id = data.get('order_id') - prod_order = data.get('prod_order') - quantity = data.get('quantity') - - if not pdf_url: - raise ValueError("PDF URL is required") - - # Download PDF - logger.info(f"Downloading PDF from: {pdf_url}") - pdf_path = self.download_pdf(pdf_url) - - # Print PDF page by page - logger.info(f"Printing PDF to: {printer_name}") - print_result = self.print_pdf_pages(pdf_path, printer_name) - - # Update service stats - self.server.last_print_time = datetime.now().isoformat() - self.server.total_jobs = getattr(self.server, 'total_jobs', 0) + 1 - - # Clean up temporary file - try: - os.unlink(pdf_path) - except: - pass - - response = { - "success": True, - "message": f"PDF printed successfully to {printer_name}", - "order_id": order_id, - "prod_order": prod_order, - "quantity": quantity, - "pages_printed": print_result.get('pages', 0), - "printer_used": print_result.get('printer', printer_name), - "method": "windows_service_page_by_page" - } - - logger.info(f"Print job completed: {response}") - self.send_json_response(200, response) - - except Exception as e: - logger.error(f"Error printing PDF: {e}") - response = { - "success": False, - "error": str(e), - "method": "windows_service_error" - } - self.send_json_response(500, response) - - def handle_print_url(self): - """Alternative endpoint that accepts PDF URL and prints it""" - try: - content_length = int(self.headers['Content-Length']) - post_data = self.rfile.read(content_length) - data = json.loads(post_data.decode('utf-8')) - - # Same logic as handle_print_pdf - self.handle_print_pdf() - - except Exception as e: - logger.error(f"Error in print_url endpoint: {e}") - self.send_error(500, str(e)) - - def download_pdf(self, pdf_url): - """Download PDF from URL to temporary file""" - try: - # Create temporary file - temp_dir = tempfile.gettempdir() - temp_file = tempfile.NamedTemporaryFile( - suffix='.pdf', - prefix='quality_label_', - delete=False, - dir=temp_dir - ) - temp_path = temp_file.name - temp_file.close() - - logger.info(f"Downloading PDF to: {temp_path}") - - # Download the PDF - urllib.request.urlretrieve(pdf_url, temp_path) - - logger.info(f"PDF downloaded successfully: {os.path.getsize(temp_path)} bytes") - return temp_path - - except Exception as e: - logger.error(f"Error downloading PDF: {e}") - raise - - def print_pdf_pages(self, pdf_path, printer_name): - """Print PDF page by page using Windows printing""" - try: - logger.info(f"Starting page-by-page printing of: {pdf_path}") - - # Method 1: Use Adobe Reader command line (if available) - adobe_result = self.try_adobe_print(pdf_path, printer_name) - if adobe_result['success']: - return adobe_result - - # Method 2: Use SumatraPDF (lightweight, good for automation) - sumatra_result = self.try_sumatra_print(pdf_path, printer_name) - if sumatra_result['success']: - return sumatra_result - - # Method 3: Use Windows PowerShell - powershell_result = self.try_powershell_print(pdf_path, printer_name) - if powershell_result['success']: - return powershell_result - - # Method 4: Use Python PDF library + Windows printing - python_result = self.try_python_print(pdf_path, printer_name) - return python_result - - except Exception as e: - logger.error(f"Error printing PDF pages: {e}") - return {"success": False, "error": str(e), "pages": 0} - - def try_adobe_print(self, pdf_path, printer_name): - """Try printing with Adobe Reader""" - try: - # Common Adobe Reader paths - adobe_paths = [ - r"C:\Program Files\Adobe\Acrobat DC\Acrobat\Acrobat.exe", - r"C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe", - r"C:\Program Files\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" - ] - - adobe_path = None - for path in adobe_paths: - if os.path.exists(path): - adobe_path = path - break - - if not adobe_path: - return {"success": False, "reason": "Adobe Reader not found"} - - # Adobe command line printing - if printer_name == 'default': - cmd = [adobe_path, "/t", pdf_path] - else: - cmd = [adobe_path, "/t", pdf_path, printer_name] - - logger.info(f"Running Adobe print command: {cmd}") - result = subprocess.run(cmd, capture_output=True, text=True, timeout=30) - - if result.returncode == 0: - logger.info("Adobe Reader print successful") - return { - "success": True, - "method": "adobe_reader", - "printer": printer_name, - "pages": "unknown" # Adobe doesn't return page count - } - else: - logger.warning(f"Adobe print failed: {result.stderr}") - return {"success": False, "reason": f"Adobe error: {result.stderr}"} - - except Exception as e: - logger.warning(f"Adobe print method failed: {e}") - return {"success": False, "reason": str(e)} - - def try_sumatra_print(self, pdf_path, printer_name): - """Try printing with SumatraPDF""" - try: - # SumatraPDF is lightweight and good for automation - sumatra_paths = [ - r"C:\Program Files\SumatraPDF\SumatraPDF.exe", - r"C:\Program Files (x86)\SumatraPDF\SumatraPDF.exe" - ] - - sumatra_path = None - for path in sumatra_paths: - if os.path.exists(path): - sumatra_path = path - break - - if not sumatra_path: - return {"success": False, "reason": "SumatraPDF not found"} - - # SumatraPDF command line printing - if printer_name == 'default': - cmd = [sumatra_path, "-print-to-default", pdf_path] - else: - cmd = [sumatra_path, "-print-to", printer_name, pdf_path] - - logger.info(f"Running SumatraPDF command: {cmd}") - result = subprocess.run(cmd, capture_output=True, text=True, timeout=30) - - if result.returncode == 0: - logger.info("SumatraPDF print successful") - return { - "success": True, - "method": "sumatra_pdf", - "printer": printer_name, - "pages": "unknown" - } - else: - logger.warning(f"SumatraPDF print failed: {result.stderr}") - return {"success": False, "reason": f"SumatraPDF error: {result.stderr}"} - - except Exception as e: - logger.warning(f"SumatraPDF print method failed: {e}") - return {"success": False, "reason": str(e)} - - def try_powershell_print(self, pdf_path, printer_name): - """Try printing with PowerShell""" - try: - # PowerShell script to print PDF - if printer_name == 'default': - ps_script = f''' - Add-Type -AssemblyName System.Drawing - $pdf = New-Object System.Drawing.Printing.PrintDocument - $pdf.DocumentName = "{os.path.basename(pdf_path)}" - Start-Process -FilePath "{pdf_path}" -Verb Print -Wait - ''' - else: - ps_script = f''' - Add-Type -AssemblyName System.Drawing - $pdf = New-Object System.Drawing.Printing.PrintDocument - $pdf.PrinterSettings.PrinterName = "{printer_name}" - $pdf.DocumentName = "{os.path.basename(pdf_path)}" - Start-Process -FilePath "{pdf_path}" -Verb Print -Wait - ''' - - # Execute PowerShell - cmd = ["powershell", "-Command", ps_script] - logger.info("Running PowerShell print command") - result = subprocess.run(cmd, capture_output=True, text=True, timeout=45) - - if result.returncode == 0: - logger.info("PowerShell print successful") - return { - "success": True, - "method": "powershell", - "printer": printer_name, - "pages": "unknown" - } - else: - logger.warning(f"PowerShell print failed: {result.stderr}") - return {"success": False, "reason": f"PowerShell error: {result.stderr}"} - - except Exception as e: - logger.warning(f"PowerShell print method failed: {e}") - return {"success": False, "reason": str(e)} - - def try_python_print(self, pdf_path, printer_name): - """Try printing with Python libraries""" - try: - # This would require additional libraries like win32print - # For now, return a fallback method - logger.info("Python print method - using default system print") - - # Use Windows default print handler - if printer_name == 'default': - os.startfile(pdf_path, "print") - else: - # More complex implementation would be needed for specific printer - os.startfile(pdf_path, "print") - - return { - "success": True, - "method": "python_system_print", - "printer": printer_name, - "pages": "unknown" - } - - except Exception as e: - logger.error(f"Python print method failed: {e}") - return {"success": False, "reason": str(e)} - - def get_available_printers(self): - """Get list of available printers on Windows with comprehensive detection""" - printers = [] - - # Method 1: Windows API (most reliable if pywin32 is available) - if WINDOWS_PRINTING_AVAILABLE: - try: - printer_info = win32print.EnumPrinters(win32print.PRINTER_ENUM_LOCAL | win32print.PRINTER_ENUM_CONNECTIONS) - for printer in printer_info: - printer_name = printer[2] # Printer name is at index 2 - - # Check if this is the default printer - try: - default_printer = win32print.GetDefaultPrinter() - is_default = (printer_name == default_printer) - except: - is_default = False - - printers.append({ - "name": printer_name, - "display_name": printer_name, - "is_default": is_default, - "status": "available", - "type": "Windows API" - }) - - logger.info(f"Found {len(printers)} printers via Windows API") - return printers - - except Exception as e: - logger.warning(f"Windows API printer enumeration failed: {e}") - - # Method 2: PowerShell (good fallback) - if not printers: - try: - cmd = ["powershell", "-Command", "Get-Printer | Select-Object Name,Default | ConvertTo-Json"] - result = subprocess.run(cmd, capture_output=True, text=True, timeout=15, shell=True) - - if result.returncode == 0 and result.stdout.strip(): - try: - printers_data = json.loads(result.stdout) - if not isinstance(printers_data, list): - printers_data = [printers_data] # Single printer case - - for printer in printers_data: - printers.append({ - "name": printer.get("Name", "Unknown"), - "display_name": printer.get("Name", "Unknown"), - "is_default": printer.get("Default", False), - "status": "available", - "type": "PowerShell" - }) - - logger.info(f"Found {len(printers)} printers via PowerShell") - - except json.JSONDecodeError as e: - logger.warning(f"Failed to parse PowerShell printer JSON: {e}") - - except Exception as e: - logger.warning(f"PowerShell printer enumeration failed: {e}") - - # Method 3: WMIC command (older Windows compatibility) - if not printers: - try: - result = subprocess.run(['wmic', 'printer', 'get', 'name', '/format:csv'], - capture_output=True, text=True, shell=True, timeout=10) - if result.returncode == 0: - lines = result.stdout.strip().split('\n')[1:] # Skip header - for line in lines: - if line.strip() and ',' in line: - parts = line.split(',') - if len(parts) >= 2 and parts[1].strip(): - printer_name = parts[1].strip() - printers.append({ - "name": printer_name, - "display_name": printer_name, - "is_default": False, - "status": "available", - "type": "WMIC" - }) - - logger.info(f"Found {len(printers)} printers via WMIC") - - except Exception as e: - logger.warning(f"WMIC printer enumeration failed: {e}") - - # Method 4: Registry search (comprehensive fallback) - if not printers: - try: - import winreg - reg_path = r"SYSTEM\CurrentControlSet\Control\Print\Printers" - with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, reg_path) as key: - i = 0 - while True: - try: - printer_name = winreg.EnumKey(key, i) - printers.append({ - "name": printer_name, - "display_name": printer_name, - "is_default": False, - "status": "available", - "type": "Registry" - }) - i += 1 - except OSError: - break - - logger.info(f"Found {len(printers)} printers via Registry") - - except Exception as e: - logger.warning(f"Registry printer enumeration failed: {e}") - - # Fallback: Add common Windows printers - if not printers: - common_printers = [ - ("Microsoft Print to PDF", True), - ("Microsoft XPS Document Writer", False), - ("OneNote for Windows 10", False), - ("Fax", False) - ] - - for printer_name, is_default in common_printers: - printers.append({ - "name": printer_name, - "display_name": f"{printer_name} (Built-in)", - "is_default": is_default, - "status": "available", - "type": "Built-in" - }) - - logger.info(f"Using {len(printers)} built-in printer options") - - # Ensure we have at least one default option - if not printers: - printers.append({ - "name": "default", - "display_name": "System Default Printer", - "is_default": True, - "status": "available", - "type": "Fallback" - }) - - logger.info(f"Total available printers: {len(printers)}") - return printers - - def send_json_response(self, status_code, data): - """Send JSON response""" - self.send_response(status_code) - self.send_header('Content-type', 'application/json') - self.send_header('Access-Control-Allow-Origin', '*') - self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS') - self.send_header('Access-Control-Allow-Headers', 'Content-Type') - self.end_headers() - - json_data = json.dumps(data, indent=2) - self.wfile.write(json_data.encode('utf-8')) - - def do_OPTIONS(self): - """Handle CORS preflight requests""" - self.send_response(200) - self.send_header('Access-Control-Allow-Origin', '*') - self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS') - self.send_header('Access-Control-Allow-Headers', 'Content-Type') - self.end_headers() - -class PrintService: - def __init__(self, port=8765): - self.port = port - self.server = None - self.running = False - - def start(self): - """Start the print service""" - try: - logger.info(f"Starting Quality Label Print Service on port {self.port}") - - self.server = HTTPServer(('localhost', self.port), PrintServiceHandler) - self.server.total_jobs = 0 - self.server.last_print_time = None - - logger.info(f"Print service running at http://localhost:{self.port}") - logger.info("Available endpoints:") - logger.info(" GET /health - Health check") - logger.info(" GET /printers - List available printers") - logger.info(" GET /status - Service status") - logger.info(" POST /print_pdf - Print PDF from URL") - - self.running = True - self.server.serve_forever() - - except KeyboardInterrupt: - logger.info("Service stopped by user") - except Exception as e: - logger.error(f"Service error: {e}") - finally: - self.stop() - - def stop(self): - """Stop the print service""" - if self.server: - logger.info("Shutting down print service...") - self.server.shutdown() - self.server.server_close() - self.running = False - -if __name__ == "__main__": - service = PrintService(port=8765) - try: - service.start() - except KeyboardInterrupt: - print("\nService stopped by user") - except Exception as e: - print(f"Service failed to start: {e}") - logger.error(f"Service failed to start: {e}") \ No newline at end of file diff --git a/windows_print_service/print_service_complete.py b/windows_print_service/print_service_complete.py deleted file mode 100644 index a3a3b96..0000000 --- a/windows_print_service/print_service_complete.py +++ /dev/null @@ -1,642 +0,0 @@ -#!/usr/bin/env python3 -""" -Windows Print Service - Complete Self-Contained Version -Fixed for Windows Service Error 1053 - Proper Service Implementation -""" - -import sys -import os -import json -import logging -import subprocess -import tempfile -import shutil -import time -import signal -from datetime import datetime -from pathlib import Path -import threading -import webbrowser -from urllib.parse import urlparse, unquote -import urllib.request -import zipfile - -# Built-in HTTP server modules -from http.server import HTTPServer, BaseHTTPRequestHandler -from socketserver import ThreadingMixIn - -# Global variables for service control -service_running = True -httpd_server = None - -class ThreadingHTTPServer(ThreadingMixIn, HTTPServer): - """Handle requests in a separate thread.""" - daemon_threads = True - allow_reuse_address = True - -class PrintServiceHandler(BaseHTTPRequestHandler): - """HTTP request handler for the print service.""" - - def __init__(self, *args, **kwargs): - self.temp_dir = tempfile.mkdtemp(prefix="print_service_") - super().__init__(*args, **kwargs) - - def log_message(self, format, *args): - """Override default logging to use our logger.""" - logging.info(f"{self.client_address[0]} - {format % args}") - - def do_GET(self): - """Handle GET requests.""" - try: - if self.path == '/health': - self.send_health_response() - elif self.path == '/printers': - self.send_printers_response() - elif self.path == '/status': - self.send_status_response() - else: - self.send_error(404, "Endpoint not found") - except Exception as e: - logging.error(f"GET request error: {e}") - self.send_error(500, str(e)) - - def do_POST(self): - """Handle POST requests.""" - try: - if self.path == '/print_pdf': - self.handle_print_pdf() - else: - self.send_error(404, "Endpoint not found") - except Exception as e: - logging.error(f"POST request error: {e}") - self.send_error(500, str(e)) - - def send_health_response(self): - """Send health check response.""" - response = { - "status": "healthy", - "service": "Windows Print Service", - "version": "1.0.0", - "timestamp": datetime.now().isoformat(), - "platform": sys.platform, - "python_version": sys.version, - "temp_dir": self.temp_dir - } - self.send_json_response(response) - - def send_printers_response(self): - """Send available printers list.""" - printers = self.get_available_printers() - response = { - "success": True, - "printers": printers, - "count": len(printers), - "timestamp": datetime.now().isoformat() - } - self.send_json_response(response) - - def send_status_response(self): - """Send service status.""" - response = { - "service_name": "Windows Print Service", - "status": "running", - "uptime": time.time() - start_time, - "requests_handled": getattr(self.server, 'request_count', 0), - "last_activity": datetime.now().isoformat() - } - self.send_json_response(response) - - def handle_print_pdf(self): - """Handle PDF printing request.""" - try: - # Get content length - content_length = int(self.headers['Content-Length']) - post_data = self.rfile.read(content_length).decode('utf-8') - - # Parse JSON data - try: - data = json.loads(post_data) - except json.JSONDecodeError: - self.send_error(400, "Invalid JSON data") - return - - pdf_url = data.get('pdf_url') - printer_name = data.get('printer_name', 'default') - - if not pdf_url: - self.send_error(400, "Missing pdf_url parameter") - return - - logging.info(f"Print request - URL: {pdf_url}, Printer: {printer_name}") - - # Download and print PDF - result = self.download_and_print_pdf(pdf_url, printer_name) - - if result['success']: - response = { - "success": True, - "message": "PDF sent to printer successfully", - "printer": printer_name, - "method": result.get('method', 'unknown'), - "timestamp": datetime.now().isoformat() - } - else: - response = { - "success": False, - "error": result.get('error', 'Unknown error'), - "timestamp": datetime.now().isoformat() - } - - self.send_json_response(response) - - except Exception as e: - logging.error(f"Print PDF error: {e}") - response = { - "success": False, - "error": str(e), - "timestamp": datetime.now().isoformat() - } - self.send_json_response(response) - - def download_and_print_pdf(self, pdf_url, printer_name): - """Download PDF and send to printer.""" - try: - # Create unique filename - timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") - pdf_filename = f"print_job_{timestamp}.pdf" - pdf_path = os.path.join(self.temp_dir, pdf_filename) - - # Download PDF - logging.info(f"Downloading PDF from: {pdf_url}") - urllib.request.urlretrieve(pdf_url, pdf_path) - - if not os.path.exists(pdf_path): - return {"success": False, "error": "Failed to download PDF"} - - logging.info(f"PDF downloaded to: {pdf_path}") - - # Try different printing methods - print_methods = [ - self.print_with_adobe_reader, - self.print_with_sumatra_pdf, - self.print_with_powershell, - self.print_with_edge, - self.print_with_system_default - ] - - for method in print_methods: - try: - result = method(pdf_path, printer_name) - if result['success']: - # Clean up downloaded file after successful print - try: - os.remove(pdf_path) - except: - pass - return result - except Exception as e: - logging.warning(f"Print method {method.__name__} failed: {e}") - continue - - return {"success": False, "error": "All printing methods failed"} - - except Exception as e: - logging.error(f"Download and print error: {e}") - return {"success": False, "error": str(e)} - - def print_with_adobe_reader(self, pdf_path, printer_name): - """Print using Adobe Reader command line.""" - try: - # Common Adobe Reader paths - adobe_paths = [ - r"C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe", - r"C:\Program Files\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe", - r"C:\Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32.exe", - r"C:\Program Files\Adobe\Reader 11.0\Reader\AcroRd32.exe" - ] - - adobe_exe = None - for path in adobe_paths: - if os.path.exists(path): - adobe_exe = path - break - - if not adobe_exe: - return {"success": False, "error": "Adobe Reader not found"} - - # Build command - if printer_name == 'default': - cmd = [adobe_exe, "/t", pdf_path] - else: - cmd = [adobe_exe, "/t", pdf_path, printer_name] - - logging.info(f"Adobe Reader command: {' '.join(cmd)}") - result = subprocess.run(cmd, capture_output=True, text=True, timeout=30) - - if result.returncode == 0: - return {"success": True, "method": "Adobe Reader"} - else: - return {"success": False, "error": f"Adobe Reader failed: {result.stderr}"} - - except subprocess.TimeoutExpired: - return {"success": False, "error": "Adobe Reader timeout"} - except Exception as e: - return {"success": False, "error": f"Adobe Reader error: {e}"} - - def print_with_sumatra_pdf(self, pdf_path, printer_name): - """Print using SumatraPDF.""" - try: - # Common SumatraPDF paths - sumatra_paths = [ - r"C:\Program Files\SumatraPDF\SumatraPDF.exe", - r"C:\Program Files (x86)\SumatraPDF\SumatraPDF.exe", - os.path.join(os.environ.get('LOCALAPPDATA', ''), 'SumatraPDF', 'SumatraPDF.exe') - ] - - sumatra_exe = None - for path in sumatra_paths: - if os.path.exists(path): - sumatra_exe = path - break - - if not sumatra_exe: - return {"success": False, "error": "SumatraPDF not found"} - - # Build command - if printer_name == 'default': - cmd = [sumatra_exe, "-print-dialog", pdf_path] - else: - cmd = [sumatra_exe, "-print-to", printer_name, pdf_path] - - logging.info(f"SumatraPDF command: {' '.join(cmd)}") - result = subprocess.run(cmd, capture_output=True, text=True, timeout=30) - - return {"success": True, "method": "SumatraPDF"} - - except subprocess.TimeoutExpired: - return {"success": False, "error": "SumatraPDF timeout"} - except Exception as e: - return {"success": False, "error": f"SumatraPDF error: {e}"} - - def print_with_powershell(self, pdf_path, printer_name): - """Print using PowerShell.""" - try: - if printer_name == 'default': - powershell_cmd = f''' - $pdf = "{pdf_path}" - Start-Process -FilePath $pdf -Verb Print -WindowStyle Hidden - ''' - else: - # Use specific printer with PowerShell - powershell_cmd = f''' - $printer = "{printer_name}" - $pdf = "{pdf_path}" - $shell = New-Object -ComObject Shell.Application - $file = $shell.NameSpace((Get-Item $pdf).DirectoryName).ParseName((Get-Item $pdf).Name) - $file.InvokeVerb("print") - ''' - - cmd = ["powershell", "-Command", powershell_cmd] - logging.info("PowerShell print command executed") - - result = subprocess.run(cmd, capture_output=True, text=True, timeout=30) - return {"success": True, "method": "PowerShell"} - - except subprocess.TimeoutExpired: - return {"success": False, "error": "PowerShell timeout"} - except Exception as e: - return {"success": False, "error": f"PowerShell error: {e}"} - - def print_with_edge(self, pdf_path, printer_name): - """Print using Microsoft Edge.""" - try: - # Convert to file URL - file_url = f"file:///{pdf_path.replace(os.sep, '/')}" - - cmd = ["msedge", "--print-to-pdf", "--run-all-compositor-stages-before-draw", file_url] - logging.info("Edge print command executed") - - result = subprocess.run(cmd, capture_output=True, text=True, timeout=30) - return {"success": True, "method": "Microsoft Edge"} - - except subprocess.TimeoutExpired: - return {"success": False, "error": "Edge timeout"} - except Exception as e: - return {"success": False, "error": f"Edge error: {e}"} - - def print_with_system_default(self, pdf_path, printer_name): - """Print using system default application.""" - try: - # Use Windows shell to open and print - cmd = ["cmd", "/c", "start", "/wait", pdf_path] - logging.info("System default print executed") - - result = subprocess.run(cmd, capture_output=True, text=True, timeout=30) - return {"success": True, "method": "System Default"} - - except subprocess.TimeoutExpired: - return {"success": False, "error": "System default timeout"} - except Exception as e: - return {"success": False, "error": f"System default error: {e}"} - - def get_available_printers(self): - """Get list of available printers using Windows commands.""" - try: - printers = [] - - # Method 1: Use PowerShell to get printers - try: - cmd = ["powershell", "-Command", "Get-Printer | Select-Object Name, Type, PrinterStatus | ConvertTo-Json"] - result = subprocess.run(cmd, capture_output=True, text=True, timeout=10) - - if result.returncode == 0: - printer_data = json.loads(result.stdout) - if isinstance(printer_data, list): - for printer in printer_data: - printers.append({ - "name": printer.get("Name", "Unknown"), - "type": printer.get("Type", "Unknown"), - "status": printer.get("PrinterStatus", "Unknown"), - "is_default": False - }) - else: - printers.append({ - "name": printer_data.get("Name", "Unknown"), - "type": printer_data.get("Type", "Unknown"), - "status": printer_data.get("PrinterStatus", "Unknown"), - "is_default": False - }) - except: - pass - - # Method 2: Use wmic command as fallback - if not printers: - try: - cmd = ["wmic", "printer", "get", "name,default", "/format:csv"] - result = subprocess.run(cmd, capture_output=True, text=True, timeout=10) - - if result.returncode == 0: - lines = result.stdout.strip().split('\n')[1:] # Skip header - for line in lines: - parts = line.split(',') - if len(parts) >= 3: - printer_name = parts[2].strip() - is_default = parts[1].strip().lower() == 'true' - if printer_name: - printers.append({ - "name": printer_name, - "type": "Windows Printer", - "status": "Available", - "is_default": is_default - }) - except: - pass - - # Add default fallback printers - if not printers: - printers = [ - {"name": "Microsoft Print to PDF", "type": "Virtual", "status": "Available", "is_default": False}, - {"name": "Default Printer", "type": "System", "status": "Available", "is_default": True} - ] - - return printers - - except Exception as e: - logging.error(f"Error getting printers: {e}") - return [{"name": "Default Printer", "type": "System", "status": "Unknown", "is_default": True}] - - def send_json_response(self, data, status_code=200): - """Send JSON response.""" - self.send_response(status_code) - self.send_header('Content-type', 'application/json') - self.send_header('Access-Control-Allow-Origin', '*') - self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS') - self.send_header('Access-Control-Allow-Headers', 'Content-Type') - self.end_headers() - - json_response = json.dumps(data, indent=2) - self.wfile.write(json_response.encode('utf-8')) - -def setup_logging(): - """Setup logging configuration.""" - 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"print_service_{datetime.now().strftime('%Y%m%d')}.log") - - logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(levelname)s - %(message)s', - handlers=[ - logging.FileHandler(log_file), - logging.StreamHandler(sys.stdout) - ] - ) - -def create_windows_service(): - """Create Windows service registration script.""" - service_script = ''' -@echo off -echo Installing Windows Print Service... - -REM Check for administrator privileges -net session >nul 2>&1 -if %errorLevel% == 0 ( - echo Administrator privileges confirmed. -) else ( - echo This script requires administrator privileges. - echo Please right-click and "Run as administrator" - pause - exit /b 1 -) - -REM Get current directory -set CURRENT_DIR=%~dp0 - -REM Install service using sc command -sc create "WindowsPrintService" binPath= "%CURRENT_DIR%print_service_complete.exe" DisplayName= "Windows Print Service" start= auto - -REM Configure service recovery options -sc failure "WindowsPrintService" reset= 86400 actions= restart/5000/restart/5000/restart/5000 - -REM Start the service -sc start "WindowsPrintService" - -echo Windows Print Service installed and started successfully! -echo Service will auto-start with Windows. -echo. -echo Test the service: http://localhost:8765/health -pause -''' - - with open('install_service_complete.bat', 'w') as f: - f.write(service_script) - -def signal_handler(signum, frame): - """Handle shutdown signals gracefully.""" - global service_running, httpd_server - logging.info(f"Received signal {signum}, shutting down gracefully...") - service_running = False - - if httpd_server: - # Shutdown server in a separate thread to avoid blocking - def shutdown_server(): - try: - httpd_server.shutdown() - httpd_server.server_close() - except Exception as e: - logging.error(f"Error during server shutdown: {e}") - - shutdown_thread = threading.Thread(target=shutdown_server) - shutdown_thread.daemon = True - shutdown_thread.start() - shutdown_thread.join(timeout=5) - - logging.info("Service shutdown complete") - sys.exit(0) - -def setup_signal_handlers(): - """Setup signal handlers for graceful shutdown.""" - if hasattr(signal, 'SIGTERM'): - signal.signal(signal.SIGTERM, signal_handler) - if hasattr(signal, 'SIGINT'): - signal.signal(signal.SIGINT, signal_handler) - if hasattr(signal, 'SIGBREAK'): # Windows specific - signal.signal(signal.SIGBREAK, signal_handler) - -def main(): - """Main service function with proper Windows service support.""" - global start_time, service_running, httpd_server - start_time = time.time() - - # Setup logging first - setup_logging() - logging.info("=== Starting Windows Print Service (Complete Version) ===") - logging.info(f"Python version: {sys.version}") - logging.info(f"Platform: {sys.platform}") - logging.info(f"Process ID: {os.getpid()}") - logging.info(f"Command line args: {sys.argv}") - - # Setup signal handlers for graceful shutdown - setup_signal_handlers() - - # Determine run mode - run_mode = "standalone" - if len(sys.argv) > 1: - if sys.argv[1] in ['--service', 'service']: - run_mode = "windows_service" - elif sys.argv[1] in ['--standalone', 'standalone']: - run_mode = "standalone" - elif sys.argv[1] in ['--test', 'test']: - run_mode = "test" - - logging.info(f"Running in '{run_mode}' mode") - - if run_mode == "test": - # Test mode - just verify setup and exit - logging.info("=== SERVICE TEST MODE ===") - test_service_setup() - return - - try: - # Start HTTP server - server_address = ('localhost', 8765) - - # Try to bind to the port - try: - httpd_server = ThreadingHTTPServer(server_address, PrintServiceHandler) - except OSError as e: - if "Address already in use" in str(e): - logging.error(f"Port 8765 is already in use. Another service instance may be running.") - logging.error("Stop the existing service or use a different port.") - return - else: - raise - - logging.info(f"Print service started on http://{server_address[0]}:{server_address[1]}") - logging.info("Available endpoints:") - logging.info(" GET /health - Health check") - logging.info(" GET /printers - List available printers") - logging.info(" GET /status - Service status") - logging.info(" POST /print_pdf - Print PDF file") - - # Keep track of requests - httpd_server.request_count = 0 - - # Service main loop - logging.info("Service is ready and listening...") - - if run_mode == "standalone": - logging.info("*** STANDALONE MODE - Press Ctrl+C to stop ***") - logging.info("Test the service at: http://localhost:8765/health") - - while service_running: - try: - # Handle requests with timeout to check service_running periodically - httpd_server.timeout = 1.0 - httpd_server.handle_request() - except KeyboardInterrupt: - logging.info("Service stopped by user (Ctrl+C)") - break - except Exception as e: - logging.error(f"Request handling error: {e}") - # Continue running unless it's a critical error - if not service_running: - break - - except Exception as e: - logging.error(f"Critical service error: {e}") - import traceback - logging.error(f"Traceback: {traceback.format_exc()}") - finally: - # Cleanup - if httpd_server: - try: - httpd_server.server_close() - except: - pass - - logging.info("=== Windows Print Service shutdown complete ===") - - # Exit cleanly - sys.exit(0) - -def test_service_setup(): - """Test service setup and configuration.""" - logging.info("Testing service setup...") - - # Test printer detection - try: - # Create a temporary handler instance to test printer detection - import tempfile - temp_handler = PrintServiceHandler() - temp_handler.temp_dir = tempfile.mkdtemp(prefix="test_service_") - - printers = temp_handler.get_available_printers() - logging.info(f"Found {len(printers)} printers:") - for printer in printers[:5]: # Show first 5 - logging.info(f" - {printer.get('name', 'Unknown')}") - - # Cleanup temp directory - try: - import shutil - shutil.rmtree(temp_handler.temp_dir) - except: - pass - - except Exception as e: - logging.warning(f"Printer detection test failed: {e}") - - # Test port availability - try: - import socket - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: - s.bind(('localhost', 8765)) - logging.info("Port 8765 is available ✓") - except OSError as e: - logging.error(f"Port 8765 test failed: {e}") - - logging.info("Service setup test completed") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/windows_print_service/requirements_complete.txt b/windows_print_service/requirements_complete.txt deleted file mode 100644 index fabd1f4..0000000 --- a/windows_print_service/requirements_complete.txt +++ /dev/null @@ -1,35 +0,0 @@ -# Windows Print Service - Complete Requirements -# All dependencies needed for the self-contained service - -# Core Python libraries (usually built-in) -# These should be available in any Python 3.7+ installation - -# For HTTP server -http.server -socketserver -urllib.request -urllib.parse - -# For system operations -os -sys -subprocess -tempfile -shutil -pathlib - -# For data handling -json -logging -threading -time -datetime - -# For Windows-specific operations -# These are handled by subprocess calls to Windows commands - -# Optional: PyInstaller for creating standalone executable -# PyInstaller==5.13.2 - -# Note: This service is designed to work with Python standard library only -# No external dependencies required for basic functionality \ No newline at end of file diff --git a/windows_print_service/service_installer.py b/windows_print_service/service_installer.py deleted file mode 100644 index 40df564..0000000 --- a/windows_print_service/service_installer.py +++ /dev/null @@ -1,259 +0,0 @@ -""" -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''' - - - 2025-09-26T12:00:00 - Quality Print Service - Quality Print Service - Automatic Label Printing - - - - true - - - - - S-1-5-18 - HighestAvailable - - - - IgnoreNew - false - false - true - true - false - - false - false - - true - true - false - false - false - PT0S - 7 - - PT5M - 3 - - - - - "{python_exe}" - "{service_script}" --service - {service_script.parent} - - -''' - - # 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") \ No newline at end of file diff --git a/windows_print_service/service_wrapper.py b/windows_print_service/service_wrapper.py deleted file mode 100644 index 8764a73..0000000 --- a/windows_print_service/service_wrapper.py +++ /dev/null @@ -1,175 +0,0 @@ -#!/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()) \ No newline at end of file diff --git a/windows_print_service/test_service.bat b/windows_print_service/test_service.bat deleted file mode 100644 index c591eba..0000000 --- a/windows_print_service/test_service.bat +++ /dev/null @@ -1,57 +0,0 @@ -@echo off -REM Windows Print Service - Troubleshooting and Testing Script -REM Use this to test the service before installing it as a Windows service - -echo ========================================= -echo Windows Print Service - Test Mode -echo ========================================= -echo. - -REM Set variables -set CURRENT_DIR=%~dp0 -set SERVICE_NAME=QualityPrintService -set INSTALL_DIR=C:\QualityPrintService -set PYTHON_EXE=%INSTALL_DIR%\python_embedded\python.exe -set PYTHON_SCRIPT=%INSTALL_DIR%\print_service_complete.py - -echo [INFO] Testing service in standalone mode... -echo [INFO] This helps diagnose issues before installing as Windows service -echo. - -REM Check if files exist -if not exist "%PYTHON_EXE%" ( - echo [ERROR] Python not found at: %PYTHON_EXE% - echo [INFO] Make sure the service is installed first using install_service_complete.bat - pause - exit /b 1 -) - -if not exist "%PYTHON_SCRIPT%" ( - echo [ERROR] Service script not found at: %PYTHON_SCRIPT% - echo [INFO] Make sure the service is installed first using install_service_complete.bat - pause - exit /b 1 -) - -echo [INFO] Files found, starting service test... -echo [INFO] Python: %PYTHON_EXE% -echo [INFO] Script: %PYTHON_SCRIPT% -echo. -echo [INFO] Starting service in test mode... -echo [INFO] Press Ctrl+C to stop the service -echo [INFO] Service will run on http://localhost:8765 -echo. - -REM Change to service directory -cd /d "%INSTALL_DIR%" - -REM Start service in standalone mode for testing -"%PYTHON_EXE%" "%PYTHON_SCRIPT%" --standalone - -echo. -echo [INFO] Service test completed. -echo [INFO] If the service ran successfully above, you can now: -echo [INFO] 1. Test it: http://localhost:8765/health -echo [INFO] 2. Start Windows service: net start %SERVICE_NAME% -echo. -pause \ No newline at end of file diff --git a/windows_print_service/uninstall_service_complete.bat b/windows_print_service/uninstall_service_complete.bat deleted file mode 100644 index 0ab7f6f..0000000 --- a/windows_print_service/uninstall_service_complete.bat +++ /dev/null @@ -1,89 +0,0 @@ -@echo off -echo ======================================== -echo Quality Print Service - Uninstaller -echo ======================================== -echo. - -REM Check for administrator privileges -net session >nul 2>&1 -if %errorLevel% neq 0 ( - echo ERROR: This uninstaller requires Administrator privileges. - echo Please right-click this file and select "Run as administrator" - echo. - pause - exit /b 1 -) - -echo Administrator privileges confirmed ✓ -echo. - -set SERVICE_NAME=QualityPrintService -set INSTALL_DIR=C:\QualityPrintService -set LOG_DIR=%USERPROFILE%\PrintService - -echo Removing Quality Print Service... -echo. - -REM Stop and remove Windows service -echo [1/4] Stopping Windows service... -sc stop "%SERVICE_NAME%" >nul 2>&1 -if %errorLevel% equ 0 ( - echo Service stopped ✓ - timeout /t 3 >nul -) else ( - echo Service was not running -) - -echo [2/4] Removing Windows service... -sc delete "%SERVICE_NAME%" >nul 2>&1 -if %errorLevel% equ 0 ( - echo Service removed ✓ -) else ( - echo Service was not installed or already removed -) - -REM Remove scheduled task fallback -echo [3/4] Removing scheduled task (if exists)... -schtasks /delete /tn "%SERVICE_NAME%" /f >nul 2>&1 -if %errorLevel% equ 0 ( - echo Scheduled task removed ✓ -) else ( - echo No scheduled task found -) - -REM Remove installation files -echo [4/4] Removing installation files... -if exist "%INSTALL_DIR%" ( - echo Removing installation directory: %INSTALL_DIR% - rmdir /s /q "%INSTALL_DIR%" >nul 2>&1 - if %errorLevel% equ 0 ( - echo Installation directory removed ✓ - ) else ( - echo WARNING: Could not remove all installation files - echo You may need to manually delete: %INSTALL_DIR% - ) -) else ( - echo Installation directory not found -) - -echo. -echo ======================================== -echo Uninstallation Complete -echo ======================================== -echo. -echo What was removed: -echo ✓ Windows service: %SERVICE_NAME% -echo ✓ Installation files: %INSTALL_DIR% -echo ✓ Scheduled task (if existed) -echo. -echo What was kept (optional cleanup): -echo - Log files: %LOG_DIR% -echo - Chrome extension (manual removal required) -echo. -echo To completely remove logs: -echo rmdir /s /q "%LOG_DIR%" -echo. -echo To remove Chrome extension: -echo Go to chrome://extensions/ and remove "Quality Print Service" -echo. -pause \ No newline at end of file