affba2a9ca
- connectorx via collect_all() eingebunden statt hiddenimports (Rust-PYD + __init__.py + Metadaten als Einheit) - SQL/CSV-Ressourcen (src/res/) ins PyInstaller-Bundle aufgenommen - Pfadauflösung in database.py auf sys._MEIPASS umgestellt für installierten Modus - connectorx als explizite Abhängigkeit in pyproject.toml ergänzt - Dokumentation (windows_distribution.md) um collect_all-Pattern und _MEIPASS-Hinweise erweitert - Version auf 1.0.0 aktualisiert, Hersteller-Informationen ergänzt
405 lines
9.7 KiB
Markdown
405 lines
9.7 KiB
Markdown
# Windows Distribution Guide für DocuMentor
|
||
|
||
## Überblick
|
||
|
||
Dieses Dokument beschreibt, wie DocuMentor für Windows-Benutzer ohne Python-Installation verpackt wird.
|
||
|
||
## Voraussetzungen
|
||
|
||
### Auf dem Entwicklungssystem
|
||
|
||
```bash
|
||
# Dependencies installieren (inkl. PyInstaller)
|
||
uv sync --all-groups
|
||
```
|
||
|
||
### Für Setup.exe (optional)
|
||
|
||
- **Inno Setup**: Download von https://jrsoftware.org/isdl.php
|
||
- Oder **WiX Toolset** für MSI: https://wixtoolset.org/
|
||
|
||
## Build-Prozess
|
||
|
||
### Option 1: Einfacher Build (ZIP-Distribution)
|
||
|
||
```bash
|
||
# 1. PyInstaller installieren
|
||
uv sync --all-groups
|
||
|
||
# 2. Build ausführen
|
||
uv run python build_windows.py
|
||
```
|
||
|
||
Dies erstellt:
|
||
- `dist/DocuMentor/DocuMentor.exe` - Eigenständige Executable
|
||
- `dist/DocuMentor-YYYYMMDD-Windows.zip` - Portable ZIP-Archiv
|
||
|
||
### Option 2: Professionelle Setup.exe mit Inno Setup
|
||
|
||
```bash
|
||
# 1. PyInstaller Build
|
||
uv run python build_windows.py
|
||
|
||
# 2. Inno Setup Compiler ausführen
|
||
iscc installer.iss
|
||
```
|
||
|
||
Dies erstellt:
|
||
- `dist/installer/DocuMentor-Setup-0.1.0.exe` - Professioneller Installer
|
||
|
||
### Option 3: MSI-Installer mit WiX
|
||
|
||
**Voraussetzungen:**
|
||
```bash
|
||
# WiX Toolset v6 installieren (aktuell)
|
||
dotnet tool install --global wix
|
||
```
|
||
|
||
**Schritt 1: PyInstaller Build erstellen**
|
||
```bash
|
||
uv run python build_windows.py
|
||
```
|
||
|
||
**Schritt 2: ProductFiles.wxs generieren**
|
||
|
||
**WICHTIG**: WiX v6 hat das `heat` Tool entfernt. Stattdessen verwenden wir ein Python-Skript:
|
||
|
||
```bash
|
||
# Generiert automatisch ProductFiles.wxs mit allen Dateien aus dist/DocuMentor
|
||
uv run python generate_wix_files.py
|
||
```
|
||
|
||
**Schritt 3: MSI kompilieren**
|
||
```bash
|
||
# WiX v6 Build
|
||
wix build DocuMentor.wxs ProductFiles.wxs -o DocuMentor.msi
|
||
```
|
||
|
||
**Hinweis**: Die Dateien `DocuMentor.wxs` und `generate_wix_files.py` sind bereits im Repository vorhanden und WiX v4/v6-kompatibel.
|
||
|
||
**Schritt 4: MSI testen**
|
||
```bash
|
||
# Installation (als Administrator)
|
||
msiexec /i DocuMentor.msi
|
||
|
||
# Silent Installation für Deployment
|
||
msiexec /i DocuMentor.msi /quiet /qn /norestart
|
||
|
||
# Deinstallation
|
||
msiexec /x DocuMentor.msi
|
||
```
|
||
|
||
**MSI-Vorteile gegenüber Inno Setup:**
|
||
- ✅ Windows-Standard (`.msi` Format)
|
||
- ✅ Gruppen-Richtlinien-Deployment (GPO)
|
||
- ✅ Silent Installation für Enterprise
|
||
- ✅ Windows Installer Service Transaktionen
|
||
- ✅ Rollback bei Fehlern
|
||
- ✅ Patch-Unterstützung (.msp)
|
||
|
||
**Build-Automatisierung (`build_msi.py`):**
|
||
```python
|
||
"""WiX MSI Build-Skript für DocuMentor (WiX v6)"""
|
||
import subprocess
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
def build_msi():
|
||
project_root = Path(__file__).parent
|
||
dist_dir = project_root / "dist" / "DocuMentor"
|
||
|
||
if not dist_dir.exists():
|
||
print("Fehler: PyInstaller Build nicht gefunden. Erst build_windows.py ausführen!")
|
||
sys.exit(1)
|
||
|
||
# Schritt 1: ProductFiles.wxs generieren (ersetzt heat)
|
||
print("Generiere ProductFiles.wxs...")
|
||
subprocess.run([
|
||
"uv", "run", "python", "generate_wix_files.py"
|
||
], check=True)
|
||
|
||
# Schritt 2: MSI kompilieren mit WiX v6
|
||
print("Kompiliere MSI-Installer...")
|
||
subprocess.run([
|
||
"wix", "build",
|
||
"DocuMentor.wxs",
|
||
"ProductFiles.wxs",
|
||
"-o", "DocuMentor.msi"
|
||
], check=True)
|
||
|
||
print("\n[OK] MSI erstellt: DocuMentor.msi")
|
||
|
||
if __name__ == "__main__":
|
||
build_msi()
|
||
```
|
||
|
||
## Manuelle Schritte
|
||
|
||
### 1. PyInstaller direkt verwenden
|
||
|
||
```bash
|
||
# Cleanup
|
||
rm -rf build/ dist/
|
||
|
||
# Build
|
||
uv run pyinstaller --clean DocuMentor.spec
|
||
|
||
# Testen
|
||
dist/DocuMentor/DocuMentor.exe
|
||
```
|
||
|
||
### 2. Anpassungen vornehmen
|
||
|
||
**Icon hinzufügen:**
|
||
1. Icon-Datei (`.ico`) im Projekt speichern, z.B. `resources/icon.ico`
|
||
2. In `DocuMentor.spec` anpassen:
|
||
```python
|
||
icon='resources/icon.ico'
|
||
```
|
||
|
||
**Versionsinformationen:**
|
||
In `DocuMentor.spec` erweitern:
|
||
```python
|
||
exe = EXE(
|
||
# ...
|
||
version='version_info.txt', # Windows-Versionsinformationen
|
||
)
|
||
```
|
||
|
||
## PyInstaller .spec Konfiguration
|
||
|
||
Die Datei `DocuMentor.spec` enthält:
|
||
|
||
- **datas**: UI-Dateien (.ui), Ressource-Dateien (SQL, CSV) und connectorx-Package
|
||
- **binaries**: Native Extensions (connectorx `.pyd`)
|
||
- **hiddenimports**: Alle notwendigen PySide6/Polars-Module
|
||
- **collect_all('connectorx')**: Sammelt Python-Code, native `.pyd`-Extension und Metadaten als Einheit (nötig, da `polars` connectorx erst zur Laufzeit per `importlib.import_module()` lädt)
|
||
- **console=False**: GUI-Anwendung ohne Konsole
|
||
- **upx=True**: Kompression der Binaries
|
||
|
||
### Wichtige Einstellungen
|
||
|
||
```python
|
||
# Ein-Datei-Build (alles in einer .exe)
|
||
exe = EXE(
|
||
pyz,
|
||
a.scripts,
|
||
a.binaries, # Diese Zeilen
|
||
a.zipfiles, # auskommentieren
|
||
a.datas, # für One-File
|
||
# ...
|
||
onefile=True, # Hinzufügen
|
||
)
|
||
```
|
||
|
||
**Achtung**: One-File-Build ist langsamer beim Start, da alles temporär entpackt werden muss.
|
||
|
||
## Distribution
|
||
|
||
### ZIP-Archive
|
||
|
||
```bash
|
||
# Automatisch durch build_windows.py erstellt
|
||
dist/DocuMentor-YYYYMMDD-Windows.zip
|
||
```
|
||
|
||
**Vorteile:**
|
||
- Einfach, portable
|
||
- Keine Installation nötig
|
||
- Kann auf USB-Stick verwendet werden
|
||
|
||
**Nachteile:**
|
||
- Keine Deinstallationsroutine
|
||
- Keine Verknüpfungen
|
||
- Keine Registry-Einträge
|
||
|
||
### Setup.exe mit Inno Setup
|
||
|
||
**Vorteile:**
|
||
- Professionell
|
||
- Deinstallation integriert
|
||
- Start-Menü und Desktop-Icons
|
||
- Update-Mechanismus möglich
|
||
|
||
**Nachteile:**
|
||
- Benötigt Administrator-Rechte (optional)
|
||
- Komplexere Konfiguration
|
||
|
||
### MSI-Installer (WiX)
|
||
|
||
**Vorteile:**
|
||
- Windows-Standard (.msi Format)
|
||
- Gruppen-Richtlinien-Deployment (GPO) für Enterprise
|
||
- Silent Installation möglich (`msiexec /quiet`)
|
||
- Windows Installer Transaktionen und Rollback
|
||
- Patch-Unterstützung (.msp für Updates)
|
||
- Deinstallation über Systemsteuerung integriert
|
||
- Versionsupgrades automatisch verwaltet
|
||
|
||
**Nachteile:**
|
||
- Komplexere Erstellung als Inno Setup
|
||
- Benötigt WiX Toolset (kostenlos)
|
||
- XML-basierte Konfiguration
|
||
- Lernkurve für WiX-Syntax
|
||
|
||
## Externe Abhängigkeiten
|
||
|
||
DocuMentor benötigt diese Tools (NICHT im Installer enthalten):
|
||
|
||
1. **Java Runtime Environment (JRE) 11+**
|
||
- Für Saxon und Apache FOP
|
||
- Download: https://adoptium.net/
|
||
|
||
2. **Apache FOP**
|
||
- XSL-FO zu PDF Konvertierung
|
||
- Download: https://xmlgraphics.apache.org/fop/
|
||
|
||
3. **Saxon XSLT Prozessor**
|
||
- XSLT 2.0/3.0 Transformationen
|
||
- Download: https://www.saxonica.com/
|
||
|
||
4. **diff-pdf**
|
||
- PDF-Vergleich
|
||
- Download: https://vslavik.github.io/diff-pdf/
|
||
|
||
### Benutzer-Anleitung
|
||
|
||
Nach der Installation:
|
||
|
||
1. DocuMentor starten
|
||
2. Beim ersten Start öffnet sich automatisch die Einstellungen
|
||
3. Pfade zu Java, Saxon, FOP und diff-pdf konfigurieren
|
||
4. Projekt-Verzeichnis wählen oder neues Projekt erstellen
|
||
|
||
## Testing
|
||
|
||
### Lokales Testing (Linux/WSL)
|
||
|
||
```bash
|
||
# Build für Windows erstellen
|
||
uv run python build_windows.py
|
||
|
||
# Executable mit Wine testen (falls verfügbar)
|
||
wine dist/DocuMentor/DocuMentor.exe
|
||
```
|
||
|
||
### Testing auf Windows
|
||
|
||
1. ZIP auf Windows-System kopieren
|
||
2. Entpacken
|
||
3. `DocuMentor.exe` ausführen
|
||
4. Alle Features testen:
|
||
- Projekt öffnen/erstellen
|
||
- Tree-Navigation
|
||
- PDF-Generierung
|
||
- Einstellungen
|
||
|
||
## Troubleshooting
|
||
|
||
### Problem: "Module not found" Fehler
|
||
|
||
**Lösung A** – Einfache Python-Module: Hidden imports in `DocuMentor.spec` ergänzen:
|
||
```python
|
||
hiddenimports=[
|
||
# ... existing
|
||
'missing_module',
|
||
]
|
||
```
|
||
|
||
**Lösung B** – Packages mit nativen Extensions (Rust/C, z.B. `connectorx`):
|
||
`hiddenimports` allein reicht nicht, da PyInstaller die `__init__.py` ins PYZ-Archiv packt, aber die `.pyd`-Extension separat im Dateisystem erwartet. Stattdessen `collect_all` verwenden:
|
||
```python
|
||
from PyInstaller.utils.hooks import collect_all
|
||
cx_datas, cx_binaries, cx_hiddenimports = collect_all('problematic_package')
|
||
|
||
a = Analysis(
|
||
# ...
|
||
binaries=cx_binaries,
|
||
datas=cx_datas,
|
||
hiddenimports=cx_hiddenimports,
|
||
)
|
||
```
|
||
|
||
### Problem: UI-Dateien oder Ressourcen nicht gefunden
|
||
|
||
**Lösung**: Prüfen ob datas korrekt konfiguriert. Ressource-Pfade müssen im Code PyInstaller-kompatibel aufgelöst werden (`sys._MEIPASS`):
|
||
```python
|
||
# In DocuMentor.spec:
|
||
datas=[
|
||
('src/ui/*.ui', 'ui'),
|
||
('src/res/*', 'res'),
|
||
]
|
||
|
||
# Im Code:
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
if hasattr(sys, "_MEIPASS"):
|
||
res_path = Path(sys._MEIPASS) / "res" / "data.sql"
|
||
else:
|
||
res_path = Path(__file__).parents[3] / "src" / "res" / "data.sql"
|
||
```
|
||
|
||
### Problem: Executable zu groß
|
||
|
||
**Lösungen**:
|
||
1. UPX-Kompression aktivieren (bereits aktiv)
|
||
2. Excludes hinzufügen für ungenutzte Module:
|
||
```python
|
||
excludes=['tkinter', 'matplotlib', 'test', 'unittest']
|
||
```
|
||
3. One-File-Build verwenden (langsamer Start)
|
||
|
||
### Problem: Antivirus blockiert
|
||
|
||
**Lösung**:
|
||
- Code-Signing-Zertifikat verwenden
|
||
- Bei Microsoft einreichen für SmartScreen
|
||
- README mit Hinweis erweitern
|
||
|
||
## Automatisierung mit CI/CD
|
||
|
||
### GitHub Actions Beispiel
|
||
|
||
```yaml
|
||
name: Build Windows Release
|
||
|
||
on:
|
||
push:
|
||
tags:
|
||
- 'v*'
|
||
|
||
jobs:
|
||
build:
|
||
runs-on: windows-latest
|
||
steps:
|
||
- uses: actions/checkout@v3
|
||
|
||
- name: Install uv
|
||
uses: astral-sh/setup-uv@v1
|
||
|
||
- name: Build
|
||
run: uv run python build_windows.py
|
||
|
||
- name: Create Release
|
||
uses: softprops/action-gh-release@v1
|
||
with:
|
||
files: dist/*.zip
|
||
```
|
||
|
||
## Versionierung
|
||
|
||
Version in folgenden Dateien aktualisieren:
|
||
1. `pyproject.toml` - `version = "X.Y.Z"`
|
||
2. `installer.iss` - `#define MyAppVersion "X.Y.Z"`
|
||
3. Optional: `src/version.py` erstellen
|
||
|
||
## Lizenz und Rechtliches
|
||
|
||
- Alle Python-Dependencies sind in der Distribution enthalten
|
||
- PySide6 (LGPL): Dynamische Verlinkung ist OK
|
||
- Polars (MIT): Unproblematisch
|
||
- Pydantic (MIT): Unproblematisch
|
||
|
||
Externe Tools (Saxon, FOP) haben eigene Lizenzen und müssen separat installiert werden.
|