Windows 11 VMware VM: Build & Test Portable ZIP
This guide provides copyable commands for building and testing the PRISM Validator portable ZIP inside a Windows 11 VMware VM.
Prerequisites (One-Time Setup)
1. Install Python 3.8+
Download and install: https://www.python.org/downloads/
✅ Critical: Check “Add Python to PATH” during installation
Verify installation:
python --version
2. Install Git (Optional)
Download: https://git-scm.com/download/win
Or if you already have the code, skip this.
Quick Build & Test (Copy-Paste Each Section)
Step 1: Open PowerShell in Project Directory
# Navigate to prism-validator directory
cd C:\Users\karl\github\prism-validator
Step 2: Clean Previous Builds (Optional but Recommended)
# Remove old build artifacts
Remove-Item -Recurse -Force .\build -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force .\dist -ErrorAction SilentlyContinue
Step 3: Setup Environment with Build Dependencies
# Run setup script with build flag
.\setup.ps1 -Build
Expected Output:
Creates
.venvfolderInstalls all dependencies
Installs PyInstaller
Step 4: Activate Virtual Environment
# Activate venv
.\.venv\Scripts\Activate.ps1
You should see (.venv) in your prompt.
Step 5: Build the Application
# Run the build script
python scripts\build\build_app.py
Build Time: ~2-5 minutes depending on VM resources
Expected Output:
Building PRISM Validator...
Version: 1.8.2
Creating Windows executable...
[... PyInstaller output ...]
✅ Build complete!
Note: This build uses app/prism-studio.py as the entry point (not the root prism-studio.py wrapper), which is required for the frozen exe to work correctly.
Step 6: Verify Build Output
# Check that executable exists
Test-Path .\dist\PrismValidator\PrismValidator.exe
Should return True
# List contents of dist folder
Get-ChildItem .\dist\PrismValidator\ | Select-Object Name, Length
Expected Files:
PrismValidator.exe(main executable, ~5-10 MB)_internal/folder (contains bundled Python runtime and dependencies)
Note: The templates/, static/, schemas/, and src/ folders are bundled inside the .exe file, not as separate folders. This is PyInstaller’s “onefile” mode - everything is packaged into the single executable.
Step 7: Create Portable ZIP
# Stop any running instances first (files must not be in use)
Get-Process -Name "PrismValidator" -ErrorAction SilentlyContinue | Stop-Process -Force
# Compress the entire directory into a ZIP
Compress-Archive -Path .\dist\PrismValidator\* -DestinationPath .\dist\PrismValidator-Portable.zip -Force
Important: The process must be stopped before creating the ZIP, otherwise files will be locked.
Step 8: Verify ZIP File
# Check ZIP file size and properties
Get-Item .\dist\PrismValidator-Portable.zip | Select-Object Name, Length, LastWriteTime
Expected Size: ~40-80 MB (since it’s a onefile build with everything bundled in the .exe)
Testing the Portable ZIP
Test 1: Run Executable In-Place
# Run the executable from dist folder
.\dist\PrismValidator\PrismValidator.exe
# Wait a few seconds, then check if it's running
Start-Sleep -Seconds 3
Get-Process -Name "PrismValidator" -ErrorAction SilentlyContinue
# If running, open browser manually (in case auto-open failed)
Start-Process "http://localhost:5001"
Expected Behavior:
Process starts (check Task Manager or
Get-Process)Web browser should auto-launch at
http://localhost:5001No console window appears (since it’s a GUI app)
If browser doesn’t auto-open, manually go to http://localhost:5001
If nothing happens:
To close:
Close browser tab
Right-click system tray icon (if any) → Exit
Or:
Get-Process PrismValidator | Stop-Process
Test 2: Extract ZIP to Temp Location
# Create temp test directory
$TestDir = "$env:TEMP\PrismValidator-Test"
New-Item -ItemType Directory -Path $TestDir -Force
# Extract ZIP to temp location
Expand-Archive -Path .\dist\PrismValidator-Portable.zip -DestinationPath $TestDir -Force
# List extracted files
Get-ChildItem $TestDir | Select-Object Name
Test 3: Run from Extracted Location
# Run from temp directory
& "$TestDir\PrismValidator.exe"
Expected Behavior:
Same as Test 1
Application runs without dependencies
Truly portable (no installation needed)
Test 4: Validate with Demo Dataset
# First, ensure app is running from Test 2/3
# Then manually:
# 1. Open browser to http://localhost:5001
# 2. Click "Choose Folder"
# 3. Navigate to: C:\Users\karl\github\prism-validator\demo
# 4. Click "Validate Dataset"
Expected Result:
Validation completes
Report shows dataset structure
No errors for demo dataset
Test 5: Check File Size & Dependencies
# Check executable size
(Get-Item .\dist\PrismValidator\PrismValidator.exe).Length / 1MB
# Check _internal folder size
(Get-ChildItem .\dist\PrismValidator\_internal -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB
# Check total directory size
(Get-ChildItem .\dist\PrismValidator\ -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB
Expected Sizes:
PrismValidator.exe: ~5-10 MB (contains all your code and data files)_internal/: ~30-60 MB (Python runtime, libraries, dependencies)Total: ~40-80 MB
Test 6: Test Without Virtual Environment
# Deactivate venv
deactivate
# Remove Python from PATH temporarily (optional extreme test)
$env:PATH = ($env:PATH -split ';' | Where-Object { $_ -notlike '*Python*' }) -join ';'
# Try running executable
.\dist\PrismValidator\PrismValidator.exe
Expected Behavior:
Still works! (Proving it’s truly standalone)
Cleanup Test Environment
# Remove temp test directory
Remove-Item -Recurse -Force "$env:TEMP\PrismValidator-Test" -ErrorAction SilentlyContinue
# Stop any running PrismValidator processes
Get-Process -Name "PrismValidator" -ErrorAction SilentlyContinue | Stop-Process -Force
Troubleshooting
Build Fails: “Python not found”
# Check Python installation
python --version
# If not found, verify PATH
$env:PATH -split ';' | Select-String Python
Build Fails: “Module not found”
# Ensure you're in venv
.\.venv\Scripts\Activate.ps1
# Reinstall dependencies
pip install -r requirements.txt
pip install -r requirements-build.txt
Executable Doesn’t Launch / Nothing Happens
First, check if it’s actually running:
# Check if process is running
Get-Process -Name "PrismValidator" -ErrorAction SilentlyContinue
# If running, try opening browser manually
Start-Process "http://localhost:5001"
If not running, check for errors:
# Run with visible console to see errors
Start-Process powershell -ArgumentList "-NoExit", "-Command", "cd '$PWD\dist\PrismValidator'; .\PrismValidator.exe"
Alternative: Check Windows Event Viewer:
# Check application event log for errors
Get-EventLog -LogName Application -Source "Application Error" -Newest 5 | Where-Object {$_.Message -like "*PrismValidator*"}
Common issues:
Port 5001 already in use
Missing dependencies in
_internal/folderAntivirus blocking execution
App crashes immediately on startup
“Access Denied” or Antivirus Blocks
# Temporarily disable Windows Defender (not recommended for production)
Set-MpPreference -DisableRealtimeMonitoring $true
# Add exclusion for dist folder
Add-MpPreference -ExclusionPath "C:\Users\karl\github\prism-validator\dist"
# Re-enable after testing
Set-MpPreference -DisableRealtimeMonitoring $false
Port 5001 Already in Use
# Find what's using port 5001
Get-NetTCPConnection -LocalPort 5001 -ErrorAction SilentlyContinue
# Kill the process
Stop-Process -Id <PID> -Force
Complete Start-to-Finish Script (Copy All)
# ============================================
# PRISM Validator: Complete Build & Test
# ============================================
# Navigate to project
cd C:\Users\karl\github\prism-validator
# Clean previous builds
Write-Host "🧹 Cleaning previous builds..." -ForegroundColor Yellow
Remove-Item -Recurse -Force .\build -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force .\dist -ErrorAction SilentlyContinue
# Setup environment
Write-Host "📦 Setting up environment..." -ForegroundColor Yellow
.\setup.ps1 -Build
# Activate venv
Write-Host "🔧 Activating virtual environment..." -ForegroundColor Yellow
.\.venv\Scripts\Activate.ps1
# Build
Write-Host "🏗️ Building application..." -ForegroundColor Yellow
python scripts\build\build_app.py
# Verify build
Write-Host "✅ Verifying build..." -ForegroundColor Green
if (Test-Path .\dist\PrismValidator\PrismValidator.exe) {
Write-Host " Build successful!" -ForegroundColor Green
$exeSize = (Get-Item .\dist\PrismValidator\PrismValidator.exe).Length / 1MB
Write-Host " Executable size: $($exeSize.ToString('F2')) MB" -ForegroundColor Cyan
} else {
Write-Host " ❌ Build failed - executable not found!" -ForegroundColor Red
exit 1
}
# Create ZIP
Write-Host "📦 Creating portable ZIP..." -ForegroundColor Yellow
Compress-Archive -Path .\dist\PrismValidator\* -DestinationPath .\dist\PrismValidator-Portable.zip -Force
$zipSize = (Get-Item .\dist\PrismValidator-Portable.zip).Length / 1MB
Write-Host " ZIP created: $($zipSize.ToString('F2')) MB" -ForegroundColor Green
# Test extraction
Write-Host "🧪 Testing ZIP extraction..." -ForegroundColor Yellow
$TestDir = "$env:TEMP\PrismValidator-Test"
Remove-Item -Recurse -Force $TestDir -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Path $TestDir -Force | Out-Null
Expand-Archive -Path .\dist\PrismValidator-Portable.zip -DestinationPath $TestDir -Force
Write-Host " Extracted to: $TestDir" -ForegroundColor Cyan
# Launch test
Write-Host "🚀 Launching from extracted location..." -ForegroundColor Yellow
Write-Host " Starting PrismValidator.exe..." -ForegroundColor Cyan
Start-Process -FilePath "$TestDir\PrismValidator.exe"
Write-Host ""
Write-Host "============================================" -ForegroundColor Green
Write-Host "✅ Build & Test Complete!" -ForegroundColor Green
Write-Host "============================================" -ForegroundColor Green
Write-Host ""
Write-Host "📂 Build location: .\dist\PrismValidator\" -ForegroundColor Cyan
Write-Host "📦 ZIP location: .\dist\PrismValidator-Portable.zip" -ForegroundColor Cyan
Write-Host "🧪 Test extraction: $TestDir" -ForegroundColor Cyan
Write-Host ""
Write-Host "🌐 Application should open in browser at http://localhost:5001" -ForegroundColor Yellow
Write-Host ""
Write-Host "Press Ctrl+C to stop PrismValidator process" -ForegroundColor Gray
Manual Testing Checklist
After running the build, manually verify:
[ ] Executable launches without errors
[ ] Browser opens to
http://localhost:5001[ ] Web interface loads correctly
[ ] Can select demo dataset folder
[ ] Validation completes successfully
[ ] Can view validation report
[ ] Can close application cleanly
[ ] ZIP file is portable (test on different directory)
[ ] No Python installation required to run
[ ] No console window appears (GUI app)
[ ] File size reasonable (~40-80 MB total, onefile build)
[ ] Only 2 items in dist folder:
PrismValidator.exeand_internal/
Distribution
Once tested, distribute the ZIP file:
# Copy ZIP to shared location
Copy-Item .\dist\PrismValidator-Portable.zip -Destination "\\NetworkShare\Software\PrismValidator.zip"
# Or create a GitHub release artifact
# (See RELEASE_GUIDE.md for GitHub Actions automation)
Notes
VM Performance: Build time depends on VM CPU cores and RAM allocation. Recommend at least 2 cores and 4GB RAM.
Antivirus: Windows Defender may flag unsigned executables. See WINDOWS_BUILD.md for code signing options.
Updates: Always clean build directory (
.\buildand.\dist) before creating release builds.Version: Version number is read from
app/src/__init__.py
Key Takeaways
What Was Fixed
Problem: Users reported that the executable from GitHub releases would start (process appeared) but the browser wouldn’t open, and nothing would happen.
Root Cause: PyInstaller was using the root prism-studio.py wrapper as the entry point, which expected an app/ folder structure that doesn’t exist in a frozen executable. This affected both local builds AND GitHub Actions builds.
Solution: Changed the default entry point in scripts/build/build_app.py from prism-studio.py to app/prism-studio.py, which:
Has proper logging configured for frozen apps (writes to
~/prism_studio.log)Handles
sys._MEIPASScorrectly for bundled resourcesDoesn’t rely on directory structure that won’t exist in frozen executables
Impact:
✅ Local builds: Now work correctly (your VM builds)
✅ GitHub Actions: Next release will work correctly
⚠️ Previous GitHub releases: Have this bug (users should use next release)
Note: The PrismValidator.spec file had the correct entry point, but PyInstaller was generating a new spec on-the-fly from build_app.py, ignoring the existing .spec file.
Build Configuration
Entry Point:
app/prism-studio.py(not rootprism-studio.py)Mode:
--onedir(directory-based distribution)Console:
--windowed(no console window, GUI only)Bundled Data: templates/, static/, schemas/, src/, official/, survey_library/
Testing the Build
Check process:
Get-Process -Name "PrismValidator"Check port:
Get-NetTCPConnection -LocalPort 5001Check log:
Get-Content "$env:USERPROFILE\prism_studio.log"Manual browser:
Start-Process "http://localhost:5001"
Quick Reference
Command |
Purpose |
|---|---|
|
Setup environment + PyInstaller |
|
Activate virtual environment |
|
Build executable |
|
Run executable |
|
Create ZIP |
|
Kill running instances |
|
Clean build artifacts |