Files
xsl-validator/docs/windows_distribution.md
T
info c3d1bbc74c Docs: WiX MSI-Installer Anleitung zu Windows Distribution hinzugefügt
- Vollständige WiX-Konfiguration (DocuMentor.wxs)
- Heat-Tool für automatisches File Harvesting
- Build-Automatisierung mit build_msi.py
- Silent Installation und GPO-Deployment
- MSI-Vorteile vs. Inno Setup detailliert erklärt
2026-01-18 17:58:37 +01:00

13 KiB

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

# Dependencies installieren (inkl. PyInstaller)
uv sync --all-groups

Für Setup.exe (optional)

Build-Prozess

Option 1: Einfacher Build (ZIP-Distribution)

# 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

# 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:

# WiX Toolset v4 installieren (empfohlen)
dotnet tool install --global wix

# Oder WiX v3 von https://wixtoolset.org/releases/

Schritt 1: PyInstaller Build erstellen

uv run python build_windows.py

Schritt 2: WiX-Konfiguration erstellen (DocuMentor.wxs):

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  
  <!-- Produkt-Definition -->
  <Product 
    Id="*" 
    Name="DocuMentor" 
    Language="1031" 
    Version="0.1.0" 
    Manufacturer="Ihr Name/Firma" 
    UpgradeCode="PUT-YOUR-UPGRADE-GUID-HERE">
    
    <Package 
      InstallerVersion="200" 
      Compressed="yes" 
      InstallScope="perMachine" 
      Description="Professionelle XSL-Transformations-Verwaltung" 
      Comments="DocuMentor - XSL/PDF Management Tool" />

    <!-- Upgrade-Logik (deinstalliert alte Versionen) -->
    <MajorUpgrade 
      DowngradeErrorMessage="Eine neuere Version ist bereits installiert." 
      AllowSameVersionUpgrades="yes" />
    
    <MediaTemplate EmbedCab="yes" />

    <!-- Feature-Definition -->
    <Feature Id="ProductFeature" Title="DocuMentor" Level="1">
      <ComponentGroupRef Id="ProductComponents" />
      <ComponentRef Id="ApplicationShortcut" />
      <ComponentRef Id="DesktopShortcut" />
    </Feature>

    <!-- UI-Dialoge (Standard-Installer-Oberfläche) -->
    <UIRef Id="WixUI_InstallDir" />
    <Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
    
    <!-- Icon für Programme und Funktionen -->
    <Icon Id="icon.ico" SourceFile="resources\icon.ico"/>
    <Property Id="ARPPRODUCTICON" Value="icon.ico" />
    
    <!-- Website-Link in Systemsteuerung -->
    <Property Id="ARPHELPLINK" Value="https://github.com/IhrRepo/DocuMentor" />
  </Product>

  <!-- Fragment: Verzeichnisstruktur -->
  <Fragment>
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
        <Directory Id="INSTALLFOLDER" Name="DocuMentor" />
      </Directory>
      
      <!-- Start-Menü -->
      <Directory Id="ProgramMenuFolder">
        <Directory Id="ApplicationProgramsFolder" Name="DocuMentor"/>
      </Directory>
      
      <!-- Desktop -->
      <Directory Id="DesktopFolder" Name="Desktop" />
    </Directory>
  </Fragment>

  <!-- Fragment: Komponenten (Dateien) -->
  <Fragment>
    <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
      <!-- Hauptexecutable -->
      <Component Id="MainExecutable" Guid="PUT-COMPONENT-GUID-HERE">
        <File Id="DocuMentorEXE" Source="dist\DocuMentor\DocuMentor.exe" KeyPath="yes" />
      </Component>
      
      <!-- Alle weiteren Dateien aus dist/DocuMentor/ -->
      <!-- HINWEIS: In Produktion heat.exe verwenden für automatisches Harvesting -->
      <Component Id="AllFiles" Guid="PUT-COMPONENT-GUID-HERE-2">
        <File Id="AllFilesMarker" Source="dist\DocuMentor\*" KeyPath="yes" />
      </Component>
    </ComponentGroup>

    <!-- Start-Menü Verknüpfung -->
    <DirectoryRef Id="ApplicationProgramsFolder">
      <Component Id="ApplicationShortcut" Guid="PUT-COMPONENT-GUID-HERE-3">
        <Shortcut 
          Id="ApplicationStartMenuShortcut" 
          Name="DocuMentor" 
          Description="XSL-Transformations-Verwaltung" 
          Target="[INSTALLFOLDER]DocuMentor.exe" 
          WorkingDirectory="INSTALLFOLDER" 
          Icon="icon.ico" />
        <RemoveFolder Id="CleanUpShortCut" Directory="ApplicationProgramsFolder" On="uninstall"/>
        <RegistryValue 
          Root="HKCU" 
          Key="Software\DocuMentor" 
          Name="installed" 
          Type="integer" 
          Value="1" 
          KeyPath="yes"/>
      </Component>
    </DirectoryRef>

    <!-- Desktop Verknüpfung (optional) -->
    <DirectoryRef Id="DesktopFolder">
      <Component Id="DesktopShortcut" Guid="PUT-COMPONENT-GUID-HERE-4">
        <Shortcut 
          Id="DesktopShortcut" 
          Name="DocuMentor" 
          Target="[INSTALLFOLDER]DocuMentor.exe" 
          WorkingDirectory="INSTALLFOLDER" 
          Icon="icon.ico" />
        <RegistryValue 
          Root="HKCU" 
          Key="Software\DocuMentor" 
          Name="desktopShortcut" 
          Type="integer" 
          Value="1" 
          KeyPath="yes"/>
      </Component>
    </DirectoryRef>
  </Fragment>
</Wix>

Schritt 3: GUIDs generieren

# GUIDs mit PowerShell generieren
powershell -Command "[guid]::NewGuid()"

# Oder Python-Skript verwenden
uv run python generate_guid.py

Schritt 4: Dateien automatisch harvesten (empfohlen)

# WiX v3: Heat Tool verwenden
heat dir dist\DocuMentor -cg ProductComponents -gg -sfrag -srd -dr INSTALLFOLDER -out ProductFiles.wxs

# WiX v4:
wix heat dir dist\DocuMentor -cg ProductComponents -gg -sfrag -srd -dr INSTALLFOLDER -out ProductFiles.wxs

Schritt 5: MSI kompilieren

# WiX v3
candle DocuMentor.wxs -out obj\
light obj\DocuMentor.wixobj -out dist\installer\DocuMentor-0.1.0.msi -ext WixUIExtension

# WiX v4
wix build DocuMentor.wxs -out dist\installer\DocuMentor-0.1.0.msi

Schritt 6: MSI testen

# Installation (als Administrator)
msiexec /i dist\installer\DocuMentor-0.1.0.msi

# Silent Installation für Deployment
msiexec /i DocuMentor-0.1.0.msi /quiet /qn /norestart

# Deinstallation
msiexec /x dist\installer\DocuMentor-0.1.0.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):

"""WiX MSI Build-Skript für DocuMentor"""
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)
    
    # Heat: Dateien harvesten
    print("Harvesting Dateien mit Heat...")
    subprocess.run([
        "heat", "dir", str(dist_dir),
        "-cg", "ProductComponents",
        "-gg", "-sfrag", "-srd",
        "-dr", "INSTALLFOLDER",
        "-out", "ProductFiles.wxs"
    ], check=True)
    
    # Candle: WXS zu WIXOBJ kompilieren
    print("Kompiliere WXS-Dateien...")
    subprocess.run([
        "candle", "DocuMentor.wxs", "ProductFiles.wxs",
        "-out", "obj\\"
    ], check=True)
    
    # Light: WIXOBJ zu MSI linken
    print("Erzeuge MSI-Installer...")
    (project_root / "dist" / "installer").mkdir(exist_ok=True)
    subprocess.run([
        "light",
        "obj\\DocuMentor.wixobj",
        "obj\\ProductFiles.wixobj",
        "-out", "dist\\installer\\DocuMentor-0.1.0.msi",
        "-ext", "WixUIExtension"
    ], check=True)
    
    print("\n✅ MSI erstellt: dist\\installer\\DocuMentor-0.1.0.msi")

if __name__ == "__main__":
    build_msi()

Manuelle Schritte

1. PyInstaller direkt verwenden

# 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:
    icon='resources/icon.ico'
    

Versionsinformationen: In DocuMentor.spec erweitern:

exe = EXE(
    # ...
    version='version_info.txt',  # Windows-Versionsinformationen
)

PyInstaller .spec Konfiguration

Die Datei DocuMentor.spec enthält:

  • datas: UI-Dateien (.ui) werden mitgepackt
  • hiddenimports: Alle notwendigen PySide6/Polars-Module
  • console=False: GUI-Anwendung ohne Konsole
  • upx=True: Kompression der Binaries

Wichtige Einstellungen

# 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

# 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+

  2. Apache FOP

  3. Saxon XSLT Prozessor

  4. 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)

# 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: Hidden imports in DocuMentor.spec ergänzen:

hiddenimports=[
    # ... existing
    'missing_module',
]

Problem: UI-Dateien nicht gefunden

Lösung: Prüfen ob datas korrekt konfiguriert:

datas=[
    ('src/ui/*.ui', 'ui'),
]

Problem: Executable zu groß

Lösungen:

  1. UPX-Kompression aktivieren (bereits aktiv)
  2. Excludes hinzufügen für ungenutzte Module:
    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

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.