fix: Deinstaller, Verwaltungsfenster, Dashboard-Widerspruch, Mount-Tempo
Ampel / ampel (push) Successful in 30s
Ampel / ampel (push) Successful in 30s
Vier Meldungen des Commanders, alle nachgemessen.
1. DEINSTALLER LIEF NICHT MEHR - reproduziert mit echtem PowerShell:
Der Typ [System.Windows.Forms.MessageBox] wurde nicht gefunden.
`Add-Type -AssemblyName System.Windows.Forms` stand EINE ZEILE ZU SPAET, die
MessageBox wurde davor benutzt. Der Deinstaller starb also in seiner ersten
Arbeitszeile, jedes Mal. Zwei weitere Maengel gleich mit:
Kodierung war ASCII trotz Umlauten, und `Remove-Item -Recurse -Force
$PSScriptRoot` loescht den Ordner, in dem das laufende Skript liegt - das
klappt auf Windows nicht zuverlaessig (venv-DLLs sind geladen). Jetzt raeumt
ein losgeloestes cmd nach, sobald PowerShell weg ist. Der erzeugte Deinstaller
ist gegengeprueft: parst, BOM da, Umlaute intakt.
2. VERWALTUNGSFENSTER (Doppelklick aufs Tray). Zeigt Status, Aufgaben und Log,
plus Knoepfe fuer Rippy, Log-in-Rippy und Deinstallieren - Deinstallieren geht
damit auch aus dem Tray-Menue. Eigener PROZESS statt Fenster im Tray, weil
pystray und tkinter beide den Haupt-Thread wollen; tkinter statt WinForms,
weil es bei jeder Windows-Python-Installation dabei ist. Headless gerendert
und angesehen. Alles Fachliche kommt von Rippy (/capabilities, /jobs), damit
dort nicht eine zweite, abweichende Wahrheit steht.
3. DASHBOARD-WIDERSPRUCH. Oben stand "Akira im Laufwerk erkannt", die
Server-Status-Karte gleichzeitig "Bereit - keine Disc in Arbeit / Disc
einlegen". Zwei Aussagen, ein Blick. Die Karte fragt jetzt /devices und sagt
"Disc erkannt - wartet auf Rippen starten" samt Titel.
4. MOUNT-TEMPO. Der Commander: "150 Sekunden? Das ist verrueckt langsam." Recht
hat er. Gemessen ging die Zeit fast komplett in einen FEHLVERSUCH: `umount -l`
ist lazy, der Abbau passiert spaeter, und wer direkt danach mountet, riskiert
dass der Abbau hinter dem neuen Mount landet. Der erste Reparaturversuch
scheiterte dadurch regelmaessig - und der zweite kostete 30 s mount-Timeout
plus Pruefungen. Jetzt werden 1,5 s auf den Abbau gewartet, bevor neu
gemountet wird; die Wache prueft erstmals nach 3 s statt 10 s und benutzt zum
ERKENNEN die einfache schnelle Probe (die Doppelprobe steckt dort, wo der
Wettlauf lauert: direkt nach dem Mount).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -303,6 +303,47 @@ def log_datei_anzeigen(icon, item):
|
||||
os.startfile(LOG_PFAD) # noqa: S606 — bewusst: Standard-Editor des Nutzers
|
||||
|
||||
|
||||
# Das Verwaltungsfenster läuft als EIGENER Prozess (Begründung in
|
||||
# verwaltung.py: pystray und tkinter wollen beide den Haupt-Thread).
|
||||
_verwaltung = {"prozess": None}
|
||||
|
||||
|
||||
def verwaltung_oeffnen(icon=None, item=None):
|
||||
"""Kleines Fenster mit Status, Aufgaben und Log (Commander-Wunsch 26.07.2026).
|
||||
|
||||
Ist es schon offen, wird kein zweites gestartet — sonst sammeln sich bei
|
||||
jedem Doppelklick Fenster an.
|
||||
"""
|
||||
laeuft = _verwaltung["prozess"]
|
||||
if laeuft is not None and laeuft.poll() is None:
|
||||
return
|
||||
pythonw = os.path.join(BASIS, "venv", "Scripts", "pythonw.exe")
|
||||
if not os.path.exists(pythonw):
|
||||
pythonw = sys.executable
|
||||
_verwaltung["prozess"] = subprocess.Popen(
|
||||
[pythonw, os.path.join(BASIS, "verwaltung.py")],
|
||||
cwd=BASIS,
|
||||
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0),
|
||||
)
|
||||
|
||||
|
||||
def deinstallieren(icon, item):
|
||||
"""Deinstallation aus dem Tray heraus (Commander-Wunsch 26.07.2026).
|
||||
|
||||
Das Skript fragt selbst nach (ohne -Force), stoppt alles aus diesem Ordner —
|
||||
also auch dieses Tray — und räumt danach auf. Deshalb wird hier nichts mehr
|
||||
erwartet: Der eigene Prozess ist gleich weg.
|
||||
"""
|
||||
skript = os.path.join(BASIS, "uninstall.ps1")
|
||||
if not os.path.exists(skript):
|
||||
return
|
||||
subprocess.Popen(
|
||||
["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass",
|
||||
"-File", skript],
|
||||
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0),
|
||||
)
|
||||
|
||||
|
||||
def beenden(icon, item):
|
||||
worker_stoppen()
|
||||
icon.stop()
|
||||
@@ -312,6 +353,10 @@ menue = pystray.Menu(
|
||||
pystray.MenuItem(status_text, None, enabled=False),
|
||||
pystray.MenuItem(restzeit_text, None, enabled=False),
|
||||
pystray.Menu.SEPARATOR,
|
||||
# `default=True`: Dieser Eintrag wird beim Doppelklick aufs Symbol
|
||||
# ausgelöst — genau das hat der Commander gewünscht. Er steht zusätzlich
|
||||
# normal im Menü, damit es auch klappt, wenn der Doppelklick nicht greift.
|
||||
pystray.MenuItem("Verwaltung öffnen", verwaltung_oeffnen, default=True),
|
||||
pystray.MenuItem(
|
||||
lambda item: "Worker stoppen" if worker_laeuft() else "Worker starten",
|
||||
umschalten,
|
||||
@@ -320,6 +365,7 @@ menue = pystray.Menu(
|
||||
pystray.MenuItem("Log in Rippy anzeigen", log_in_rippy),
|
||||
pystray.MenuItem("Log-Datei auf diesem PC", log_datei_anzeigen),
|
||||
pystray.Menu.SEPARATOR,
|
||||
pystray.MenuItem("Worker deinstallieren …", deinstallieren),
|
||||
pystray.MenuItem("Beenden (stoppt den Worker)", beenden),
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user