# PowerShell Build Script for S7 Streamer & Logger # Compatible with PowerShell Core and Windows PowerShell # Function to safely handle Python process management function Show-PythonProcessDetails { param($processes) Write-Host "`nDetailed Python process information:" -ForegroundColor Cyan for ($i = 0; $i -lt $processes.Count; $i++) { $proc = $processes[$i] $commandLine = "" try { $commandLine = (Get-WmiObject Win32_Process -Filter "ProcessId = $($proc.Id)").CommandLine } catch { $commandLine = "Unable to retrieve command line" } Write-Host "[$($i+1)] PID: $($proc.Id) - $($proc.ProcessName)" -ForegroundColor White Write-Host " Window: $($proc.MainWindowTitle)" -ForegroundColor Gray Write-Host " Command: $commandLine" -ForegroundColor Gray Write-Host " Start Time: $($proc.StartTime)" -ForegroundColor Gray Write-Host "" } } Write-Host "Starting build process..." -ForegroundColor Green # Step 1: Build Frontend Write-Host "Building frontend..." -ForegroundColor Yellow Set-Location frontend try { npm run build Write-Host "Frontend build completed" -ForegroundColor Green } catch { Write-Host "Frontend build failed: $($_.Exception.Message)" -ForegroundColor Red exit 1 } # Step 2: Return to root and clean old builds Set-Location .. Write-Host "Cleaning old build directories..." -ForegroundColor Yellow if (Test-Path "build") { Remove-Item -Recurse -Force "build" Write-Host " Removed build directory" -ForegroundColor Gray } if (Test-Path "dist") { Remove-Item -Recurse -Force "dist" Write-Host " Removed dist directory" -ForegroundColor Gray } # Step 3: Activate conda environment and build with PyInstaller Write-Host "Activating conda environment and building executable..." -ForegroundColor Yellow try { # Activate conda environment conda activate snap7v12 # Run PyInstaller pyinstaller main.spec --clean Write-Host "Build completed successfully!" -ForegroundColor Green Write-Host "Results available in: dist/main/" -ForegroundColor Cyan # Wait for PyInstaller to fully release file handles Write-Host "Waiting for file handles to be released..." -ForegroundColor Yellow Start-Sleep -Seconds 3 # Check for Python processes that might hold file handles $pythonProcesses = Get-Process -Name "python*" -ErrorAction SilentlyContinue | Where-Object { $_.ProcessName -match "python" } if ($pythonProcesses.Count -gt 0) { Write-Host "`nFound $($pythonProcesses.Count) Python process(es):" -ForegroundColor Yellow $pythonProcesses | ForEach-Object { Write-Host " PID: $($_.Id) - $($_.ProcessName) - $($_.MainWindowTitle)" -ForegroundColor Gray } Write-Host "`nSome Python processes might be holding file handles that could interfere with compression." -ForegroundColor Yellow Write-Host "Options:" -ForegroundColor Cyan Write-Host " [y] Terminate ALL Python processes" -ForegroundColor White Write-Host " [d] Show DETAILED information and select specific processes" -ForegroundColor White Write-Host " [n] Keep all processes running (default)" -ForegroundColor White $response = Read-Host "Choose an option (y/d/N)" if ($response -eq 'y' -or $response -eq 'Y') { Write-Host "Terminating ALL Python processes..." -ForegroundColor Yellow try { $pythonProcesses | Stop-Process -Force -ErrorAction SilentlyContinue Write-Host "All Python processes terminated." -ForegroundColor Green } catch { Write-Host "Warning: Some processes could not be terminated: $($_.Exception.Message)" -ForegroundColor Yellow } Start-Sleep -Seconds 2 } elseif ($response -eq 'd' -or $response -eq 'D') { Show-PythonProcessDetails -processes $pythonProcesses Write-Host "Enter the numbers of processes to terminate (e.g., '1,3,5' or 'all' or 'none'):" -ForegroundColor Cyan $selection = Read-Host "Selection" if ($selection -eq 'all') { Write-Host "Terminating ALL Python processes..." -ForegroundColor Yellow $pythonProcesses | Stop-Process -Force -ErrorAction SilentlyContinue } elseif ($selection -ne 'none' -and $selection -ne '') { $indices = $selection.Split(',') | ForEach-Object { $_.Trim() } Write-Host "Terminating selected processes..." -ForegroundColor Yellow foreach ($index in $indices) { try { $processIndex = [int]$index - 1 if ($processIndex -ge 0 -and $processIndex -lt $pythonProcesses.Count) { $proc = $pythonProcesses[$processIndex] Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue Write-Host " Terminated PID $($proc.Id)" -ForegroundColor Green } else { Write-Host " Invalid index: $index" -ForegroundColor Red } } catch { Write-Host " Could not terminate process $index`: $($_.Exception.Message)" -ForegroundColor Red } } } else { Write-Host "No processes will be terminated." -ForegroundColor Yellow } Start-Sleep -Seconds 2 } else { Write-Host "Keeping all Python processes running. If compression fails, you may need to close them manually." -ForegroundColor Yellow } } else { Write-Host "No Python processes found that could interfere with build." -ForegroundColor Green } } catch { Write-Host "PyInstaller build failed: $($_.Exception.Message)" -ForegroundColor Red exit 1 } # Step 4: Compress the dist/main directory Write-Host "Compressing distribution..." -ForegroundColor Yellow $timestamp = Get-Date -Format "yyyyMMdd_HHmmss" $zipName = "S7_Streamer_Logger_$timestamp.zip" $destinationPath = "C:\Users\migue\OneDrive\Miguel\CSA - Trabajo\Software\SIDEL\09 - DIET AS REGULAR" try { # Check if destination directory exists if (-not (Test-Path $destinationPath)) { Write-Host "Creating destination directory..." -ForegroundColor Yellow New-Item -ItemType Directory -Path $destinationPath -Force | Out-Null } # Try to use 7zip first (if available) $sevenZipPaths = @( "C:\Program Files\7-Zip\7z.exe", "C:\Program Files (x86)\7-Zip\7z.exe" ) $sevenZipFound = $false foreach ($path in $sevenZipPaths) { if (Test-Path $path) { Write-Host "Using 7zip for compression..." -ForegroundColor Cyan $zipFullPath = Join-Path $destinationPath $zipName & "$path" a -tzip "$zipFullPath" ".\dist\main\*" -r $sevenZipFound = $true break } } # If 7zip not found, use PowerShell's built-in compression if (-not $sevenZipFound) { Write-Host "Using PowerShell built-in compression..." -ForegroundColor Cyan $tempZip = ".\$zipName" # Retry compression up to 3 times with delays $retryCount = 0 $maxRetries = 3 $compressionSuccess = $false while ($retryCount -lt $maxRetries -and -not $compressionSuccess) { try { if ($retryCount -gt 0) { Write-Host "Retrying compression (attempt $($retryCount + 1)/$maxRetries)..." -ForegroundColor Yellow Start-Sleep -Seconds 5 } # Force garbage collection to release any lingering file handles [System.GC]::Collect() [System.GC]::WaitForPendingFinalizers() Compress-Archive -Path ".\dist\main\*" -DestinationPath $tempZip -Force $compressionSuccess = $true } catch { $retryCount++ Write-Host "Compression attempt $retryCount failed: $($_.Exception.Message)" -ForegroundColor Yellow if ($retryCount -eq $maxRetries) { # Final attempt: try creating a copy first, then compress Write-Host "Trying alternative method: copy then compress..." -ForegroundColor Yellow $tempDir = ".\temp_build_$timestamp" if (Test-Path $tempDir) { Remove-Item -Recurse -Force $tempDir } # Copy files to temporary directory Copy-Item -Path ".\dist\main" -Destination $tempDir -Recurse -Force # Wait a moment Start-Sleep -Seconds 2 # Try to compress the copy try { Compress-Archive -Path "$tempDir\*" -DestinationPath $tempZip -Force $compressionSuccess = $true # Clean up temp directory Remove-Item -Recurse -Force $tempDir } catch { # Clean up temp directory if (Test-Path $tempDir) { Remove-Item -Recurse -Force $tempDir } throw $_ } } if (-not $compressionSuccess) { throw $_ } } } # Move to destination $zipFullPath = Join-Path $destinationPath $zipName Move-Item $tempZip $zipFullPath -Force } Write-Host "Archive created successfully!" -ForegroundColor Green Write-Host "Location: $zipFullPath" -ForegroundColor Cyan # Show file size $fileSize = (Get-Item $zipFullPath).Length / 1MB Write-Host "Archive size: $([math]::Round($fileSize, 2)) MB" -ForegroundColor Gray # Open Windows Explorer in the destination directory Write-Host "Opening destination folder..." -ForegroundColor Yellow try { # Use Windows Explorer to open the destination directory and select the ZIP file explorer.exe /select,"$zipFullPath" } catch { # Fallback: just open the directory try { explorer.exe "$destinationPath" } catch { Write-Host "Could not open Explorer automatically. File location: $zipFullPath" -ForegroundColor Yellow } } } catch { Write-Host "Compression failed: $($_.Exception.Message)" -ForegroundColor Red exit 1 } Write-Host "Build process completed!" -ForegroundColor Green