Make build_and_deploy.ps1 self-installing and fail loudly
pip install of pyinstaller/pystray/pillow was a separate manual step the
README only mentioned in prose, so the script silently died on missing
packages -- especially bad on Explorer double-click, where the window
closes before any error is visible. Consolidate all dependencies into
requirements.txt (also used by README's plain "pip install -r" flow), have
the script install it itself, wrap the whole build in try/catch with
exit-code checks after every native call, and pause on both success and
failure unless -NoPause is passed.
Also move the build output from %LOCALAPPDATA% into dist/ next to the
script, so it's easy to find and matches the already-gitignored dist/ entry.
(cherry picked from commit 13c3745479)
This commit is contained in:
parent
9e21360393
commit
02d6c0c5e9
3 changed files with 96 additions and 31 deletions
24
README.md
24
README.md
|
|
@ -41,15 +41,18 @@ falls gewünscht.
|
|||
## Voraussetzungen
|
||||
|
||||
- Python 3.11 oder neuer
|
||||
- Pakete: `pyserial` (Board-Kommunikation), `pystray` + `pillow`
|
||||
(Tray-Icon/Desktop-App), optional `mcp` (nur für den MCP-Server)
|
||||
- Alle Pakete stehen in `requirements.txt` (`pyserial` fürs Board,
|
||||
`pystray` + `pillow` fürs Tray-Icon/Desktop-Fenster, `mcp` für den
|
||||
MCP-Server, `pyinstaller` fürs `.exe`-Bauen):
|
||||
|
||||
```bash
|
||||
pip install pyserial pystray pillow mcp
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
Für den Browser-Modus (`server.py`) reicht die Python-Standardbibliothek —
|
||||
keine zusätzlichen Pakete nötig.
|
||||
keine zusätzlichen Pakete nötig. `build_and_deploy.ps1` installiert
|
||||
`requirements.txt` beim Bauen automatisch selbst — ein manuelles
|
||||
`pip install` vorher ist dafür nicht nötig.
|
||||
|
||||
## Starten
|
||||
|
||||
|
|
@ -69,8 +72,15 @@ Maschine/Python-Version unterschiedlich). Selbst bauen:
|
|||
.\build_and_deploy.ps1
|
||||
```
|
||||
|
||||
Das Skript baut mit PyInstaller (`--onedir --windowed`, eigenes Icon) und
|
||||
kopiert das Ergebnis nach `%LOCALAPPDATA%\VersaPadViewer\VersaPadViewer.exe`.
|
||||
Das Skript installiert/aktualisiert selbst alle nötigen Pakete aus
|
||||
`requirements.txt` (kein manuelles `pip install` vorher nötig), baut dann
|
||||
mit PyInstaller (`--onedir --windowed`, eigenes Icon) und kopiert das
|
||||
Ergebnis nach `dist\VersaPadViewer\VersaPadViewer.exe` im Projektordner.
|
||||
Bricht ein Schritt ab (fehlendes Python, PyInstaller-Fehler, ...), zeigt das
|
||||
Skript eine klare Fehlermeldung und wartet auf einen Tastendruck, statt sich
|
||||
bei Doppelklick im Explorer kommentarlos zu schließen (`-NoPause`
|
||||
unterdrückt das für automatisierte Aufrufe/CI).
|
||||
|
||||
**Wichtig:** Sowohl Bauen als auch Ausführen müssen auf einem lokalen
|
||||
Laufwerk passieren — von einem Netzlaufwerk (SMB-Share) aus scheitert
|
||||
PyInstaller beim Bauen (Pfadlängen-Problem mit Tcl/Tk-Zeitzonendaten) und
|
||||
|
|
@ -79,8 +89,6 @@ das Nachladen der Bundle-DLLs von einem Netzwerkpfad, ohne jede
|
|||
Fehlermeldung). `build_and_deploy.ps1` kopiert den Quellcode deshalb
|
||||
automatisch zuerst nach `%TEMP%` und baut nur dort.
|
||||
|
||||
Voraussetzung: `pip install pyinstaller` zusätzlich zu den obigen Paketen.
|
||||
|
||||
## Aufbau
|
||||
|
||||
| Datei | Zweck |
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
# Baut VersaPadViewer.exe (PyInstaller --onedir) und kopiert das Ergebnis
|
||||
# nach lokal (C:\Users\<user>\AppData\Local\VersaPadViewer).
|
||||
# nach $projectDir\dist\VersaPadViewer.
|
||||
#
|
||||
# WICHTIG: Sowohl Bauen als auch Laufen muessen lokal passieren, NICHT auf
|
||||
# dem Netzlaufwerk (Z:\Git\...):
|
||||
|
|
@ -12,35 +12,87 @@
|
|||
# SMB-Share, kombiniert mit dem eh schon langen Projektpfad.
|
||||
#
|
||||
# Deshalb: Quellcode zuerst nach lokal (%TEMP%) kopieren, dort bauen, danach
|
||||
# das fertige Bundle nach %LOCALAPPDATA% kopieren. Z: wird nur zum Lesen der
|
||||
# Quelldateien angefasst.
|
||||
# das fertige Bundle nach $projectDir\dist kopieren. Z: wird nur zum Lesen
|
||||
# der Quelldateien angefasst.
|
||||
#
|
||||
# Fehlerverhalten: Bei Doppelklick im Explorer schliesst sich das Fenster
|
||||
# sofort nach Skriptende -- ohne Pause waeren Fehlermeldungen unsichtbar
|
||||
# ("stirbt ohne jede Fehlermeldung"). Deshalb: alles in try/catch, im
|
||||
# Fehlerfall UND am Ende eine Pause, ausser bei -NoPause (fuer CI/Automation).
|
||||
|
||||
param(
|
||||
[switch]$NoPause
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$projectDir = $PSScriptRoot
|
||||
$buildSrc = "$env:TEMP\versapad_build_src"
|
||||
$localDir = "$env:LOCALAPPDATA\VersaPadViewer"
|
||||
$localDir = "$projectDir\dist\VersaPadViewer"
|
||||
$requirementsFile = "$projectDir\requirements.txt"
|
||||
|
||||
if (Test-Path $buildSrc) {
|
||||
Remove-Item $buildSrc -Recurse -Force
|
||||
function Assert-LastExitCode([string]$step) {
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "$step ist fehlgeschlagen (Exit-Code $LASTEXITCODE) -- Ausgabe oben pruefen."
|
||||
}
|
||||
}
|
||||
|
||||
function Wait-ForKeyIfInteractive {
|
||||
if ($NoPause) { return }
|
||||
try {
|
||||
Read-Host "Taste druecken zum Schliessen"
|
||||
} catch {
|
||||
# z.B. nicht-interaktiver Aufruf (stdin nicht verfuegbar) -- einfach ignorieren
|
||||
}
|
||||
}
|
||||
New-Item -ItemType Directory -Path $buildSrc | Out-Null
|
||||
Copy-Item "$projectDir\*.py" -Destination $buildSrc
|
||||
Copy-Item "$projectDir\icon.ico" -Destination $buildSrc
|
||||
Copy-Item "$projectDir\icon.png" -Destination $buildSrc
|
||||
|
||||
Push-Location $buildSrc
|
||||
try {
|
||||
Write-Host "Pruefe Python-Installation..."
|
||||
py --version
|
||||
Assert-LastExitCode "'py --version' (ist Python installiert und im PATH?)"
|
||||
|
||||
if (-not (Test-Path $requirementsFile)) {
|
||||
throw "requirements.txt nicht gefunden unter $requirementsFile"
|
||||
}
|
||||
Write-Host "Installiere/aktualisiere benoetigte Pakete aus requirements.txt..."
|
||||
py -m pip install --quiet --disable-pip-version-check -r $requirementsFile
|
||||
Assert-LastExitCode "Paketinstallation (pip install -r requirements.txt)"
|
||||
|
||||
if (Test-Path $buildSrc) {
|
||||
Remove-Item $buildSrc -Recurse -Force
|
||||
}
|
||||
New-Item -ItemType Directory -Path $buildSrc | Out-Null
|
||||
Copy-Item "$projectDir\*.py" -Destination $buildSrc
|
||||
Copy-Item "$projectDir\icon.ico" -Destination $buildSrc
|
||||
Copy-Item "$projectDir\icon.png" -Destination $buildSrc
|
||||
|
||||
Push-Location $buildSrc
|
||||
try {
|
||||
Write-Host "Baue mit PyInstaller (--onedir --windowed)..."
|
||||
py -m PyInstaller --windowed --onedir --name VersaPadViewer `
|
||||
--icon icon.ico --add-data "icon.png;." --add-data "icon.ico;." `
|
||||
desktop_viewer.py --noconfirm
|
||||
} finally {
|
||||
Assert-LastExitCode "PyInstaller-Build"
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
}
|
||||
|
||||
if (Test-Path $localDir) {
|
||||
if (-not (Test-Path "$buildSrc\dist\VersaPadViewer\VersaPadViewer.exe")) {
|
||||
throw "PyInstaller hat keine VersaPadViewer.exe erzeugt, obwohl der Exit-Code 0 war -- Build-Ausgabe oben pruefen."
|
||||
}
|
||||
|
||||
if (Test-Path $localDir) {
|
||||
Remove-Item $localDir -Recurse -Force
|
||||
}
|
||||
Copy-Item "$buildSrc\dist\VersaPadViewer" -Destination $localDir -Recurse
|
||||
Remove-Item $buildSrc -Recurse -Force
|
||||
}
|
||||
Copy-Item "$buildSrc\dist\VersaPadViewer" -Destination $localDir -Recurse
|
||||
Remove-Item $buildSrc -Recurse -Force
|
||||
|
||||
Write-Host "Fertig: $localDir\VersaPadViewer.exe"
|
||||
Write-Host ""
|
||||
Write-Host "Fertig: $localDir\VersaPadViewer.exe" -ForegroundColor Green
|
||||
Wait-ForKeyIfInteractive
|
||||
}
|
||||
catch {
|
||||
Write-Host ""
|
||||
Write-Host "FEHLER: $($_.Exception.Message)" -ForegroundColor Red
|
||||
Wait-ForKeyIfInteractive
|
||||
exit 1
|
||||
}
|
||||
|
|
|
|||
5
requirements.txt
Normal file
5
requirements.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
pyserial
|
||||
pystray
|
||||
pillow
|
||||
mcp
|
||||
pyinstaller
|
||||
Loading…
Add table
Add a link
Reference in a new issue