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 Reportfenstersehr 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:
__________________________________________________ ______________
__________________________________________________ _________________
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.
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
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)
- Import von alten Projektdateien (ETS5 etc.)
Geht noch nicht:
-
Noch optimierfähig:
-
- Scrollen im Reportfenster
-
- Die Schrift ist glaube ich nicht die normale ETS-Schriftart.
-
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 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,
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.


Kommentar