Ankündigung

Einklappen
Keine Ankündigung bisher.

KNX ETS 6.3.1 unter Linux mit Wine - ERFOLG! - mit Anleitung

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    KNX ETS 6.3.1 unter Linux mit Wine - ERFOLG! - mit Anleitung

    Hallo zusammen, hier mein erster Beitrag! 😁

    Wie so einige hier im Forum möchte ich gerne von Windows wegkommen. Die ETS war das letzte Programm, für das ich noch eine Windowsinstallation habe. Ich hatte keine Lust auf eine Container- oder VM-Lösung unter Linux, das ist immer doof, wenn man im Hintergrund erst mal quasi Windows booten muss. Out-of-the-Box klappt es mit Wine nicht. Hierzu wird sich seit geraumer Zeit auch hier im Forum der Kopf drüber zerbrochen. Auch in anderen Foren gab es keinen echten Erfolg, soweit ich das gesehen habe.

    Ich bin da schon was länger am experimentieren, aber heute hatte ich dann endlich den Durchbruch: Es läuft unter Wine/Proton-GE. Normaler Shortcut, der sofort die ETS öffnet. Keine VM, kein Container, nix! Auch habe ich keine Bugs gefunden.

    Auch wenn ich nicht so der Forenmensch bin wollte ich den Durchbruch irgendwie mit der KNX Community teilen. Bringt ja keinem was, wenn das Wissen auf meiner Festplatte vergammelt.

    Getestet und funktional:
    - Projekt anlegen, speichern, öffnen, importieren, exportieren
    - Lizenz hinzufügen / Lizenzmanagement
    - Gebäude / Gruppenadressen anlegen
    - Gruppenadressen und Kommunikationsobjekte verknüpfen
    - Online-Katalog herunterladen
    - Diagnosefunktionen (Busmonitor etc, inkl. Befehle senden)
    - IP-Gateway Kommunikation
    - Addons/DCA (getestet mit: SCN-DA64x-04 - für MDT DALI Gateway)
    - PDF Report Export
    - Drucken


    Nicht getestet:
    - USB Gateways
    - Programmieren von Geräten (das möchte ich lieber in einer Testumgebung machen, nicht an meiner echten Hausinstallation. Sollte aber funktionieren, da die Telegramme im Busmonitor korrekt rein- und rausgehen)
    - USB Lizenz Dongle (ich habe nur eine Cloud Lizenz)
    - Addons
    - Import von alten Projektdateien (ETS5 etc.)

    Geht noch nicht:
    - Drucken


    Noch optimierfähig:
    - Einige Sachen fühlen sich ein wenig träge an, bleibt aber absolut im Rahmen ETS läuft jetzt mit 64bit, deutlich schneller als vorher, aber immer noch nicht ganz durchoptimiert.
    - Scrollen im Reportfenster sehr ein wenig träge
    - Newskarusell auf der Startseite sehr träge
    - Die Schrift ist glaube ich nicht die normale ETS-Schriftart.
    - Einige UI Elemente sind, zu mindestens auf meinem 4k Monitor, kleiner als unter Windows

    Hier die Anleitung, getestet unter CatchyOS/Arch:

    __________________________________________________ ______________


    Code:
    # KNX ETS 6 unter Linux mit Wine/Proton-GE
    
    **Getestet mit:** ETS 6.3.1 (Build 8272) auf CachyOS (Arch-basiert), KDE Plasma 6, Wayland
    **Datum:** Februar 2026
    **Wine-Runtime:** GE-Proton10-32
    
    > Dies ist nach meinem aktuellem Kenntnisstand die **erste dokumentierte, funktionierende ETS 6 Installation unter Linux**. ETS 6 ist eine .NET Framework 4.8 / WPF-Anwendung, die normalerweise ausschliesslich unter Windows laeuft. Diese Anleitung beschreibt alle notwendigen Schritte inkl. der IL-Binary-Patches, die noetig sind um diverse Wine-Inkompatibilitaeten zu umgehen.
    
    ---
    
    ## Inhaltsverzeichnis
    
    1. [Voraussetzungen](#1-voraussetzungen)
    2. [Proton-GE installieren](#2-proton-ge-installieren)
    3. [Wine-Prefix erstellen](#3-wine-prefix-erstellen)
    4. [.NET Framework und Abhaengigkeiten](#4-net-framework-und-abhaengigkeiten)
    5. [ETS 6 installieren](#5-ets-6-installieren)
    6. [Binary-Patches anwenden](#6-binary-patches-anwenden)
    7. [Schriftarten installieren](#7-schriftarten-installieren)
    8. [rundll32 deaktivieren](#8-rundll32-deaktivieren)
    9. [Firewall konfigurieren](#9-firewall-konfigurieren)
    10. [KDE-Fensterdekorationen](#10-kde-fensterdekorationen)
    11. [Performance-Optimierung](#11-performance-optimierung)
    12. [Startskript und Desktop-Shortcut](#12-startskript-und-desktop-shortcut)
    13. [Bekannte Einschraenkungen](#13-bekannte-einschraenkungen)
    14. [Fehlerbehebung](#14-fehlerbehebung)
    
    ---
    
    ## 1. Voraussetzungen
    
    ### System
    - Linux-Distribution mit aktuellem Kernel (getestet: CachyOS/Arch, Kernel 6.19)
    - KDE Plasma 6 (fuer native Fensterdekorationen, andere Desktops nicht getestet)
    - ETS6
    
    ### Pakete installieren (Arch/CachyOS)
    ```bash
    # Wine-Abhaengigkeiten
    sudo pacman -S wine wine-mono wine-gecko winetricks
    
    # Build-Tools (fuer winetricks)
    sudo pacman -S cabextract p7zip
    
    # Firewall
    sudo pacman -S ufw
    ```
    
    ### ETS 6 Installer
    - ETS 6 Installer (.exe) von https://my.knx.org herunterladen
    
    ---
    
    ## 2. Proton-GE installieren
    
    Proton-GE ist ein modifizierter Wine-Build von GloriousEggroll mit besserer .NET/WPF-Kompatibilitaet als Standard-Wine.
    
    ```bash
    # Proton-GE herunterladen (Version 10-32 getestet)
    mkdir -p ~/.local/share/proton-ge
    cd ~/.local/share/proton-ge
    wget https://github.com/GloriousEggroll/proton-ge-custom/releases/download/GE-Proton10-32/GE-Proton10-32.tar.gz
    tar xzf GE-Proton10-32.tar.gz
    rm GE-Proton10-32.tar.gz
    ```
    
    Pruefen:
    ```bash
    ~/.local/share/proton-ge/GE-Proton10-32/files/bin/wine --version
    ```
    
    ---
    
    ## 3. Wine-Prefix erstellen
    
    ```bash
    export WINEPREFIX=~/.wine-ets6
    export WINE=~/.local/share/proton-ge/GE-Proton10-32/files/bin/wine
    
    # 64-Bit Prefix erstellen
    WINEARCH=win64 $WINE wineboot --init
    ```
    
    ### Wine-Mono entfernen
    Wine-Mono muss entfernt werden, da wir das native .NET Framework benoetigen:
    ```bash
    winetricks remove_mono
    ```
    
    ---
    
    ## 4. .NET Framework und Abhaengigkeiten
    
    ```bash
    export WINEPREFIX=~/.wine-ets6
    
    # .NET Framework 4.8 (inkl. 4.0 als Voraussetzung)
    winetricks dotnet40
    winetricks dotnet48
    
    # Visual C++ 2022 Runtime
    winetricks vcrun2022
    
    # Schriftarten (komplett - benoetigt fuer WPF-Rendering)
    winetricks allfonts
    ```
    
    ### Registry-Einstellungen
    Das native .NET Framework muss als bevorzugt konfiguriert werden. Dies sollte winetricks automatisch setzen, aber zur Sicherheit pruefen:
    
    ```bash
    # Pruefen ob mscoree auf native steht
    wine reg query "HKCU\Software\Wine\DllOverrides" /v "*mscoree"
    # Sollte ausgeben: *mscoree = native
    ```
    
    Falls nicht gesetzt:
    ```bash
    wine reg add "HKCU\Software\Wine\DllOverrides" /v "*mscoree" /t REG_SZ /d "native" /f
    ```
    
    ### Crash-Dialoge unterdruecken
    ```bash
    wine reg add "HKCU\Software\Wine\WineDbg" /v "ShowCrashDialog" /t REG_DWORD /d 0 /f
    ```
    
    ---
    
    ## 5. ETS 6 installieren
    
    ```bash
    export WINEPREFIX=~/.wine-ets6
    WINE=~/.local/share/proton-ge/GE-Proton10-32/files/bin/wine
    
    # ETS6 Installer ausfuehren
    $WINE /pfad/zum/ETS6_Setup.exe
    ```
    
    Die Installation sollte durchlaufen. Der Installationspfad ist standardmaessig:
    `C:\Program Files (x86)\ETS6\`
    
    ### WebView2 Runtime
    Die in dem ETS Installer mitgelieferte WebView2 Datei möchte nicht so richtig, daher per Hand vorher installieren:
    ```bash
    # Microsoft Edge WebView2 Runtime (Fixed Version 109)
    # Download von Microsoft und installieren
    $WINE /pfad/zur/MicrosoftEdgeWebView2RuntimeInstaller.exe
    ```
    
    ---
    
    ## 6. Binary-Patches anwenden
    
    > **WICHTIG:** Diese Patches sind spezifisch fuer **ETS 6.3.1 (Build 8272)**. Bei anderen Versionen muessen die Offsets angepasst werden!
    
    ETS 6 verwendet diverse Windows-APIs die unter Wine nicht (korrekt) funktionieren. Folgende .NET IL-Code-Patches sind noetig:
    
    ### Uebersicht der Patches
    
    | Bereich | Problem | Loesung |
    |---------|---------|---------|
    | TaskbarProgressManager.Initialize | ArgumentException (ITaskbarList3 nicht verfuegbar) | Setzt `_initialized=true` und return |
    | TaskbarProgressManager.EnsureInitialized | NotInitializedException | return |
    | 30 TaskbarProgressManager-Methoden | Alle greifen auf nicht-initialisierte COM-Objekte zu | return |
    | MoveNext Catch-Handler | Wine SEH kann .NET-Exceptions nicht dispatchen | SetException durch SetResult ersetzen |
    | WizardViewModelBase.Dispose | NullReferenceException bei Wizard-Cleanup | return |
    | GenericWizardViewModel.Dispose | NullReferenceException in Dispose-Kette | return |
    | SimpleWizardPage.Dispose | NullReferenceException in Dispose-Kette | return |
    
    ### Patch-Skript
    
    Speichere folgendes als `patch_ets6_dll.py` und fuehre es aus:
    
    ```python
    #!/usr/bin/env python3
    """
    Patch Knx.Ets.ViewModel.dll fuer Wine/Proton-GE Kompatibilitaet.
    Spezifisch fuer ETS 6.3.1 (Build 8272), DLL-Groesse: 18.107.280 Bytes.
    
    Patches:
    - TaskbarProgressManager: Initialize, EnsureInitialized, 30 Methoden
    - MoveNext Catch-Handler: SetException -> SetResult
    - Dispose-Kette: WizardViewModelBase, GenericWizardViewModel, SimpleWizardPage
    """
    import struct, shutil, sys, os
    
    DLL = os.path.expanduser(
    "~/.wine-ets6/drive_c/Program Files (x86)/ETS6/Knx.Ets.ViewModel.dll"
    )
    EXPECTED_SIZE = 18107280
    
    # Alle Patches: (offset, original_hex, patched_hex)
    PATCHES = [
    # === TaskbarProgressManager.Initialize ===
    # CodeSize 68 -> 8, Code: ldarg.0; ldc.i4.1; stfld _initialized; ret
    (0x0014FA98, "44", "08"),
    (0x0014FAA0, "2003000000fe0e00", "02177d3e0d00042a"),
    # === TaskbarProgressManager-Methoden (30 Stueck) -> ret ===
    (0x0014FAE8, "e6", "02"), (0x0014FAF0, "2b1f", "162a"),
    (0x0014FBDC, "f7", "01"), (0x0014FBE4, "2b", "2a"),
    (0x0014FCC0, "d6", "02"), (0x0014FCC8, "2012", "162a"),
    (0x0014FD84, "f2", "01"), (0x0014FD8C, "20", "2a"),
    (0x0014FE84, "2801", "0100"), (0x0014FE8C, "20", "2a"),
    (0x0014FFD8, "1601", "0100"), (0x0014FFE0, "20", "2a"),
    (0x001500CC, "1201", "0200"), (0x001500D4, "2060", "142a"),
    (0x001501BC, "c901", "0100"), (0x001501C4, "16", "2a"),
    (0x001503F4, "6502", "0100"), (0x001503FC, "20", "2a"),
    (0x001506D8, "2e02", "0100"), (0x001506E0, "20", "2a"),
    (0x001508C4, "ed", "01"), (0x001508CC, "02", "2a"),
    # === EnsureInitialized -> ret ===
    (0x00150960, "ab01", "0100"), (0x00150968, "16", "2a"),
    # === Weitere TaskbarProgressManager-Methoden ===
    (0x00150BA0, "cc", "01"), (0x00150BA8, "20", "2a"),
    (0x00150C68, "d3", "01"), (0x00150C70, "20", "2a"),
    (0x00150D2C, "0701", "0100"), (0x00150D34, "20", "2a"),
    (0x00150E14, "0301", "0100"), (0x00150E1C, "20", "2a"),
    (0x00150F08, "0f01", "0100"), (0x00150F10, "20", "2a"),
    (0x00150FD0, "1b", "13"),
    (0x00150FD4, "c202", "0100"), (0x00150FDC, "20", "2a"),
    (0x001512C0, "d9", "01"), (0x001512C8, "20", "2a"),
    (0x001513B8, "0101", "0200"), (0x001513C0, "2007", "142a"),
    (0x001514A8, "f7", "01"), (0x001514B0, "20", "2a"),
    (0x0015158C, "0d01", "0100"), (0x00151594, "20", "2a"),
    (0x00151698, "0601", "0100"), (0x001516A0, "20", "2a"),
    (0x0015179C, "0501", "0100"), (0x001517A4, "20", "2a"),
    (0x001518A0, "f9", "01"), (0x001518A8, "20", "2a"),
    (0x00151A0C, "7f01", "0100"), (0x00151A14, "20", "2a"),
    (0x00151B88, "d7", "02"), (0x00151B90, "203b", "162a"),
    (0x00151C5C, "d7", "01"), (0x00151C64, "20", "2a"),
    (0x00151D20, "dd", "02"), (0x00151D28, "20f5", "162a"),
    (0x00151DEC, "e1", "01"), (0x00151DF4, "20", "2a"),
    # === MoveNext Catch-Handler: SetException -> SetResult ===
    (0x0029955A, "0d", "26"), # stloc.3 -> pop
    (0x00299569, "09", "00"), # ldloc.3 -> nop-artig
    (0x0029956B, "2b", "24"), # br.s -> Methoden-Token Korrektur
    # === WizardViewModelBase.Dispose -> ret ===
    (0x00697518, "2602", "0100"), (0x00697520, "20", "2a"),
    # === GenericWizardViewModel.Dispose -> ret ===
    (0x0069F19C, "5603", "0100"), (0x0069F1A4, "20", "2a"),
    # === SimpleWizardPage.Dispose -> ret ===
    (0x006A2424, "5901", "0100"), (0x006A242C, "20", "2a"),
    ]
    
    def main():
    if not os.path.exists(DLL):
    print(f"FEHLER: DLL nicht gefunden: {DLL}")
    sys.exit(1)
    
    size = os.path.getsize(DLL)
    if size != EXPECTED_SIZE:
    print(f"WARNUNG: DLL-Groesse {size} != erwartet {EXPECTED_SIZE}")
    print("Diese Patches sind fuer ETS 6.3.1 (Build 8272)!")
    resp = input("Trotzdem fortfahren? (j/n): ")
    if resp.lower() != 'j':
    sys.exit(1)
    
    # Backup erstellen
    bak = DLL + ".bak"
    if not os.path.exists(bak):
    shutil.copy2(DLL, bak)
    print(f"Backup erstellt: {bak}")
    else:
    print(f"Backup existiert bereits: {bak}")
    
    with open(DLL, "rb") as f:
    data = bytearray(f.read())
    
    applied = 0
    skipped = 0
    errors = 0
    
    for offset, orig_hex, patch_hex in PATCHES:
    orig = bytes.fromhex(orig_hex)
    patch = bytes.fromhex(patch_hex)
    current = bytes(data[offset:o[IMG]https://knx-user-forum.de/core/image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==[/IMG]ffset+len(orig)])
    
    if current == patch:
    skipped += 1 # Bereits gepatcht
    elif current == orig:
    data[offset:offset+len(patch)] = patch
    applied += 1
    else:
    print(f" FEHLER bei 0x{offset:08X}: erwartet {orig_hex}, "
    f"gefunden {current.hex()}")
    errors += 1
    
    with open(DLL, "wb") as f:
    f.write(data)
    
    print(f"\nErgebnis: {applied} angewendet, {skipped} bereits gepatcht, "
    f"{errors} Fehler")
    if errors > 0:
    print("WARNUNG: Einige Patches konnten nicht angewendet werden!")
    print("Moeglicherweise falsche ETS-Version.")
    else:
    print("Alle Patches erfolgreich!")
    
    if __name__ == "__main__":
    main()
    ```
    
    ### Ausfuehren:
    ```bash
    python3 patch_ets6_dll.py
    ```
    
    ### Was die Patches bewirken
    
    **TaskbarProgressManager** (Wine-Problem: ITaskbarList3 COM-Interface nicht verfuegbar)
    
    ETS 6 versucht beim Start die Windows-Taskleisten-Fortschrittsanzeige zu initialisieren. Unter Wine schlaegt das fehl mit `ArgumentException: String argument cannot be null`. Der Patch:
    - `Initialize`: Setzt das interne `_initialized`-Feld auf `true` und kehrt sofort zurueck
    - `EnsureInitialized`: Kehrt sofort zurueck (prueft nicht mehr ob initialisiert)
    - 30 Property-Getter/Setter: Kehren mit Standardwert zurueck
    
    **MoveNext Catch-Handler** (Wine-Problem: SEH Frame-Validation)
    
    Wine's Structured Exception Handling (SEH) kann bestimmte .NET Exception-Frames nicht verarbeiten (`invalid frame outside stack limits`). Der Patch aendert den Catch-Handler so, dass er die Exception als Erfolg markiert statt sie weiterzuwerfen.
    
    **Dispose-Kette** (Wine-Problem: NullReferenceException bei WPF-Cleanup)
    
    Beim Schliessen von Wizard-Dialogen greifen die Dispose-Methoden auf Objekte zu, die unter Wine `null` sind. Da Wine's SEH die daraus resultierenden NullReferenceExceptions nicht abfangen kann, werden sie zu `AccessViolationException`. Der Patch macht alle drei Dispose-Methoden in der Vererbungskette zu No-Ops.
    
    ---
    
    ## 7. Schriftarten installieren
    
    ### Segoe MDL2 Assets (Fenster-Button-Icons)
    
    ETS 6 verwendet die Microsoft-Schriftart "Segoe MDL2 Assets" fuer UI-Icons (Minimieren, Maximieren, Schliessen etc.). Diese ist unter Linux nicht verfuegbar. Wir erstellen eine minimale Ersatzschriftart:
    
    ```python
    #!/usr/bin/env python3
    """Erstellt eine minimale 'Segoe MDL2 Assets' Ersatzschriftart."""
    from fontTools.fontBuilder import FontBuilder
    from fontTools.pens.ttGlyphPen import TTGlyphPen
    import os
    
    UPM = 2048
    
    def draw_close(pen):
    t = 100; s, e = 350, 1450
    pen.moveTo((s, s + t*2)); pen.lineTo((s, s + t))
    pen.lineTo((e - t, e)); pen.lineTo((e, e))
    pen.lineTo((e, e - t)); pen.lineTo((s + t, s)); pen.closePath()
    pen.moveTo((s, e - t*2)); pen.lineTo((s, e - t))
    pen.lineTo((e - t, s)); pen.lineTo((e, s))
    pen.lineTo((e, s + t)); pen.lineTo((s + t, e)); pen.closePath()
    
    def draw_minimize(pen):
    pen.moveTo((350, 800)); pen.lineTo((1450, 800))
    pen.lineTo((1450, 950)); pen.lineTo((350, 950)); pen.closePath()
    
    def draw_maximize(pen):
    t = 120; x1, y1, x2, y2 = 350, 350, 1450, 1450
    pen.moveTo((x1, y1)); pen.lineTo((x2, y1))
    pen.lineTo((x2, y2)); pen.lineTo((x1, y2)); pen.closePath()
    pen.moveTo((x1+t, y1+t)); pen.lineTo((x1+t, y2-t))
    pen.lineTo((x2-t, y2-t)); pen.lineTo((x2-t, y1+t)); pen.closePath()
    
    def draw_restore(pen):
    t = 100; fx1, fy1, fx2, fy2 = 250, 200, 1150, 1100
    pen.moveTo((fx1,fy1)); pen.lineTo((fx2,fy1))
    pen.lineTo((fx2,fy2)); pen.lineTo((fx1,fy2)); pen.closePath()
    pen.moveTo((fx1+t,fy1+t)); pen.lineTo((fx1+t,fy2-t))
    pen.lineTo((fx2-t,fy2-t)); pen.lineTo((fx2-t,fy1+t)); pen.closePath()
    bx1,by1,bx2,by2 = 600,600,1550,1500
    pen.moveTo((bx1,by2-t)); pen.lineTo((bx2,by2-t))
    pen.lineTo((bx2,by2)); pen.lineTo((bx1,by2)); pen.closePath()
    pen.moveTo((bx2-t,fy2)); pen.lineTo((bx2,fy2))
    pen.lineTo((bx2,by2-t)); pen.lineTo((bx2-t,by2-t)); pen.closePath()
    pen.moveTo((fx2,by1)); pen.lineTo((bx2-t,by1))
    pen.lineTo((bx2-t,by1+t)); pen.lineTo((fx2,by1+t)); pen.closePath()
    
    def draw_dash(pen):
    pen.moveTo((450, 850)); pen.lineTo((1350, 850))
    pen.lineTo((1350, 1050)); pen.lineTo((450, 1050)); pen.closePath()
    
    fb = FontBuilder(UPM, isTTF=True)
    names = [".notdef","close","indeterminate","minimize"," maxi mize",
    "restore","projectclose"]
    fb.setupGlyphOrder(names)
    fb.setupCharacterMap({0xE106:"close", 0xE73C:"indeterminate",
    0xE921:"minimize", 0xE922:"maximize", 0xE923:"restore",
    0xEB90:"projectclose"})
    
    funcs = {".notdef":None, "close":draw_close, "indeterminate":draw_dash,
    "minimize":draw_minimize, "maximize":draw_maximize,
    "restore":draw_restore, "projectclose":draw_close}
    glyphs, metrics = {}, {}
    for n in names:
    pen = TTGlyphPen(None)
    if funcs[n]:
    funcs[n](pen); glyphs[n] = pen.glyph(); metrics[n] = (1800, 0)
    else:
    pen.moveTo((100,0)); pen.lineTo((500,0))
    pen.lineTo((500,1400)); pen.lineTo((100,1400)); pen.closePath()
    pen.moveTo((150,50)); pen.lineTo((150,1350))
    pen.lineTo((450,1350)); pen.lineTo((450,50)); pen.closePath()
    glyphs[n] = pen.glyph(); metrics[n] = (600, 100)
    
    fb.setupGlyf(glyphs); fb.setupHorizontalMetrics(metrics)
    fb.setupHorizontalHeader(ascent=1800, descent=-200)
    fb.setupNameTable({"familyName":"Segoe MDL2 Assets","styleName":"Regular",
    "manufacturer":"Wine Substitute","version":"Version 1.0",
    "uniqueFontIdentifier":"SegoeMDL2Assets-Sub","fullName":"Segoe MDL2 Assets",
    "psName":"SegoeMDL2Assets","typographicFamily" :"Se goe MDL2 Assets",
    "typographicSubfamily":"Regular"})
    fb.setupOS2(sTypoAscender=1800, sTypoDescender=-200, sTypoLineGap=0,
    usWinAscent=1800, usWinDescent=200, sxHeight=900, sCapHeight=1400, fsType=0)
    fb.setupPost()
    
    out = os.path.expanduser(
    "~/.wine-ets6/drive_c/windows/Fonts/segmdl2.ttf")
    fb.font.save(out)
    print(f"Font gespeichert: {out}")
    ```
    
    ### Voraussetzung:
    ```bash
    pip install fonttools
    ```
    
    ### Font in Wine registrieren:
    
    Da `wine reg` den Prefix mit der System-Wine-Version kontaminieren kann, direkt in der Registry-Datei editieren:
    
    ```bash
    # In ~/.wine-ets6/system.reg folgende Zeile im Abschnitt
    # [Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts] hinzufuegen:
    # "Segoe MDL2 Assets (TrueType)"="segmdl2.ttf"
    ```
    
    Oder (wenn Prefix-Kontamination kein Problem):
    ```bash
    WINEPREFIX=~/.wine-ets6 wine reg add \
    "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Fonts" \
    /v "Segoe MDL2 Assets (TrueType)" /t REG_SZ /d "segmdl2.ttf" /f
    ```
    
    ---
    
    ## 8. rundll32 deaktivieren
    
    ETS 6 und .NET rufen beim Start `rundll32.exe` fuer Shell-Erweiterungen auf, was unter Wine zu Fehlerdialogen fuehrt.
    
    ### Loesung: rundll32.exe durch No-Op ersetzen
    
    ```python
    #!/usr/bin/env python3
    """Erstellt eine minimale PE64-EXE die sofort mit Exit-Code 0 beendet."""
    import struct, os
    
    dos = bytearray(64)
    dos[0:2] = b'MZ'
    struct.pack_into('<L', dos, 60, 64)
    coff = bytearray(20)
    struct.pack_into('<H', coff, 0, 0x8664) # AMD64
    struct.pack_into('<H', coff, 2, 1) # 1 Section
    struct.pack_into('<H', coff, 16, 0xF0) # Optional Header Size
    struct.pack_into('<H', coff, 18, 0x0022) # EXECUTABLE | LARGE_ADDRESS
    opt = bytearray(240)
    struct.pack_into('<H', opt, 0, 0x020B) # PE32+
    struct.pack_into('<L', opt, 16, 0x1000) # Entry Point RVA
    struct.pack_into('<Q', opt, 24, 0x140000000)
    struct.pack_into('<L', opt, 32, 0x1000) # Section Alignment
    struct.pack_into('<L', opt, 36, 0x200) # File Alignment
    struct.pack_into('<H', opt, 40, 6)
    struct.pack_into('<H', opt, 44, 6)
    struct.pack_into('<L', opt, 56, 0x3000) # Image Size
    struct.pack_into('<L', opt, 60, 0x200) # Headers Size
    struct.pack_into('<H', opt, 68, 2) # GUI Subsystem
    struct.pack_into('<Q', opt, 72, 0x100000)
    struct.pack_into('<Q', opt, 80, 0x1000)
    struct.pack_into('<Q', opt, 88, 0x100000)
    struct.pack_into('<Q', opt, 96, 0x1000)
    struct.pack_into('<L', opt, 108, 16)
    sec = bytearray(40)
    sec[0:6] = b'.text\x00'
    struct.pack_into('<L', sec, 8, 0x1000)
    struct.pack_into('<L', sec, 12, 0x1000)
    struct.pack_into('<L', sec, 16, 0x200)
    struct.pack_into('<L', sec, 20, 0x200)
    struct.pack_into('<L', sec, 36, 0x60000020)
    headers = dos + b'PE\x00\x00' + coff + opt + sec
    headers += b'\x00' * (0x200 - len(headers))
    code = bytearray(0x200)
    code[0:3] = b'\x31\xC0\xC3' # xor eax,eax; ret
    
    prefix = os.path.expanduser("~/.wine-ets6/drive_c/windows")
    for d in ["system32", "syswow64"]:
    path = f"{prefix}/{d}/rundll32.exe"
    bak = path + ".bak"
    if os.path.exists(path) and not os.path.exists(bak):
    os.rename(path, bak)
    with open(path, 'wb') as f:
    f.write(headers + bytes(code))
    print(f"Erstellt: {path}")
    ```
    
    Zusaetzlich in `~/.wine-ets6/user.reg` im Abschnitt `[Software\\Wine\\DllOverrides]`:
    ```
    "rundll32"=""
    ```
    
    ---
    
    ## 9. Firewall konfigurieren
    
    ETS 6 kommuniziert mit KNX IP-Gateways ueber **UDP Port 3671** (KNXnet/IP).
    
    ```bash
    # UFW aktivieren (falls noch nicht geschehen)
    sudo ufw enable
    
    # KNXnet/IP Gateway-Antworten erlauben
    sudo ufw allow 3671/udp comment "KNXnet/IP gateway responses"
    
    # Pruefen
    sudo ufw status numbered
    ```
    
    Ohne diese Regel werden die KNX IP-Gateways in ETS 6 nicht gefunden.
    
    ---
    
    ## 10. KDE-Fensterdekorationen
    
    ETS 6 (WPF/Telerik RadWindow) erstellt rahmenlose Fenster mit eigener Titelleiste. Unter Wine funktioniert diese Custom-Chrome nicht richtig. Eine KWin-Fensterregel erzwingt native KDE-Dekorationen.
    
    ### KWin-Regel erstellen
    
    Datei `~/.config/kwinrulesrc`:
    ```ini
    [General]
    count=1
    
    [1]
    Description=ETS6 Native Dekorationen
    noborder=false
    noborderrule=2
    wmclass=ets6c
    wmclasscomplete=false
    wmclassmatch=2
    ```
    
    ### Wine X11-Treiber konfigurieren
    
    In `~/.wine-ets6/user.reg` im Abschnitt `[Software\\Wine\\X11 Driver]`:
    ```
    "Decorated"="Y"
    "Managed"="Y"
    ```
    
    ### KWin-Regeln neu laden
    ```bash
    qdbus6 org.kde.KWin /KWin reconfigure
    ```
    
    ---
    
    ## 11. Performance-Optimierung
    
    ### user.settings anpassen
    
    Datei: `~/.wine-ets6/drive_c/users/<username>/AppData/Local/KNX/ETS6/user.settings`
    
    Folgende Werte aendern:
    ```xml
    <EnableTelemetry>false</EnableTelemetry> <!-- Telemetrie deaktivieren -->
    <LoadFromUrl>false</LoadFromUrl> <!-- RSS-News-Feed deaktivieren -->
    <CheckForUpdates>false</CheckForUpdates> <!-- Update-Check deaktivieren -->
    ```
    
    Die **News-/Produkt-Leiste** im Dashboard verwendet WebView2 (Chromium) und ist der vermutliche Hauptverursacher von Traegheit.
    
    ---
    
    ## 12. Startskript und Desktop-Shortcut
    
    ### Startskript (`~/ets6-proton-ge.sh`)
    
    ```bash
    #!/bin/bash
    # ETS6 Launcher mit Proton-GE
    PROTON_DIR=$HOME/.local/share/proton-ge/GE-Proton10-32/files
    
    export WINEPREFIX=$HOME/.wine-ets6
    
    # WebView2: Pfad zur Runtime
    export WEBVIEW2_BROWSER_EXECUTABLE_FOLDER="C:\\Program Files (x86)\\Microsoft\\EdgeWebView\\Application\\109.0. 1518.140"
    export WEBVIEW2_USER_DATA_FOLDER="C:\\users\\$USER\\AppDa ta\\Local\\ETS6\\WebView2"
    
    # Chromium-Flags: maximale Performance unter Wine
    export WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS="\
    --disable-gpu --disable-gpu-compositing --disable-software-rasterizer \
    --no-sandbox --single-process --in-process-gpu --no-zygote \
    --disable-features=RendererCodeIntegrity,BackForwardCache,ms SmartScreenProtection,SpareRendererForSitePerProce ss \
    --disable-breakpad --disable-crash-reporter --disable-background-networking \
    --disable-extensions --disable-default-apps --disable-component-update \
    --disable-domain-reliability --disable-sync --disable-translate \
    --disable-background-timer-throttling --disable-backgrounding-occluded-windows \
    --disable-renderer-backgrounding --disable-ipc-flooding-protection \
    --disable-hang-monitor --disable-client-side-phishing-detection \
    --no-first-run --no-default-browser-check --no-pings \
    --disable-logging --disable-speech-api --disable-notifications \
    --js-flags=--lite-mode"
    
    # .NET CLR: Stack-Groesse erhoehen (Standard 1MB -> 8MB)
    export COMPlus_DefaultStackSize=0x800000
    
    # .NET: GC Server-Modus deaktivieren (weniger Threads)
    export COMPlus_gcServer=0
    
    # Proton library paths
    export LD_LIBRARY_PATH="$PROTON_DIR/lib/x86_64-linux-gnu:$PROTON_DIR/lib/i386-linux-gnu:$LD_LIBRARY_PATH"
    export GST_PLUGIN_SYSTEM_PATH_1_0="$PROTON_DIR/lib/x86_64-linux-gnu/gstreamer-1.0:$PROTON_DIR/lib/i386-linux-gnu/gstreamer-1.0"
    
    WINE="$PROTON_DIR/bin/wine"
    
    # ETS6C.exe direkt starten (64-Bit CLR, kein WoW64)
    # Kein explorer/Virtual Desktop noetig - TaskbarProgressManager ist gepatcht
    $WINE "C:\Program Files (x86)\ETS6\ETS6C.exe" 2>&1 | \
    grep -E "err:|crit|Could not|seh:|Exception"
    ```
    
    ```bash
    chmod +x ~/ets6-proton-ge.sh
    ```
    
    ### Desktop-Shortcut (`~/Schreibtisch/ETS6.desktop`)
    
    ```ini
    [Desktop Entry]
    Name=ETS6
    Exec=/home/<username>/ets6-proton-ge.sh
    Type=Application
    StartupNotify=true
    Icon=A8C3_EtsIcons.0
    StartupWMClass=ets6c.exe
    Terminal=false
    ```
    
    ```bash
    chmod +x ~/Schreibtisch/ETS6.desktop
    ```
    
    ---
    
    ## 13. Bekannte Einschraenkungen
    
    - **WebView2-Elemente** (News-Feed, Produktplatzierungen) koennen traege sein - empfohlen: `LoadFromUrl=false`
    - **Wine SEH-Fehler** (`invalid frame ... outside stack limits`) erscheint in der Konsole - hat keinen Einfluss auf die Funktionalitaet
    - Die Patches sind **versionsspezifisch** fuer ETS 6.3.1 (Build 8272)
    
    ---
    
    ## 14. Fehlerbehebung
    
    ### AccessViolationException beim Projekt oeffnen
    - Pruefen ob alle Dispose-Patches angewendet sind
    - `Knx.Ets.ViewModel.dll` mit Backup vergleichen
    
    ### KNX Gateways werden nicht gefunden
    - Firewall pruefen: `sudo ufw status`
    - Port 3671/UDP muss offen sein
    - Gateway im selben Netzwerk-Segment?
    
    ### Fenster-Buttons fehlen (nur Quadrate)
    - Segoe MDL2 Assets Font installiert? `ls ~/.wine-ets6/drive_c/windows/Fonts/segmdl2.ttf`
    - Font in Registry registriert?
    
    ### Fenster hat keine Titelleiste
    - KWin-Regel pruefen: `cat ~/.config/kwinrulesrc`
    - KWin neu laden: `qdbus6 org.kde.KWin /KWin reconfigure`
    
    ### ETS6 startet nicht
    - Proton-GE korrekt installiert? Wine-Binary testen: `~/.local/share/proton-ge/GE-Proton10-32/files/bin/wine --version`
    - .NET Framework installiert? `ls ~/.wine-ets6/drive_c/windows/Microsoft.NET/Framework64/v4.0.30319/`
    - mscoree Override pruefen: `grep mscoree ~/.wine-ets6/user.reg`
    
    ### rundll32-Fehlermeldungen
    - No-Op EXE vorhanden? `ls -la ~/.wine-ets6/drive_c/windows/system32/rundll32.exe` (sollte 1024 Bytes sein)
    - DLL-Override gesetzt? `grep rundll32 ~/.wine-ets6/user.reg`
    
    
    ​
    __________________________________________________ _________________​

    Ich versuche das ganze mal in einem Script unterzubringen, dass die Änderungen automatisch durchführt. Aber das dauert noch etwas.

    Ich werde die Erfahrungen mit einem Testkoffer und einem USB-Gateway nachreichen, sobald ich wieder einen in die Finger bekomme. Selbes gilt für die USB-Lizenz-Dongle.

    Update 22.02.26 - 20:35 Uhr: DCA/Addons laufen.
    Update 23.02.26 - 10:36 Uhr: jetzt neu: in 64bit, deutlich mehr Performance. PDF Report Export funktioniert, Report Drucken noch nicht.
    Update 23.02.26 - 18:32 Uhr: Drucken geht, weitere Performance-Optimierungen.

    Es gibt ein noch nicht breitbandig getestetes Installationsscript. Ich stelle dies noch auf den 64bit Modus um und schaue mir noch einmal die Druckfunktion an, dann wird es veröffentlicht, sobald es ein paar Nutzer erfolgreich durchlaufen lassen konnten.
    Zuletzt geändert von RgSg86; Gestern, 18:34.

    #2
    Echt super, danke für die Anleitung! Leider ist das Wochenende nun schon vorbei und der Test muss ein paar Tage warten. ;-) Ich werde an dieser Stelle aber definitiv berichten. Danke für deine Arbeit und das Teilen!

    Kommentar


      #3
      Das Script ist fertig. Bevor ich es bei GitHub hochlade und hier verlinke wären ein paar Tester ganz nett, die sich grob mit Linux, Konsolen etc. auskennen. Das Script sollte für mehrere Distros passen, aber bisher ungetestet.

      Vielleicht per PN melden?

      Kommentar

      Lädt...
      X