Andre 9747022ad6 Feature: Wrapper, Logging und Doku überarbeitet
- Debug-Logging optional gemacht, den Legacy-Wrapper portabler aufgebaut (relative Pfade, Debug-Weitergabe, Python-Fallback) und die README für Endanwender und Entwickler klarer neu strukturiert.
2026-04-18 17:33:58 +02:00

FocusFix - Game Foreground Fix for Windows

Windows-Hilfsprogramm, das ein Spielfenster automatisch in den Vordergrund bringt. Gedacht für Spiele (z.b. Crimson Desert), die nach dem Start im Hintergrund landen oder von Steam, Taskleiste, Splashscreens oder Overlay-Fenstern verdeckt werden. Funktioniert mit Steam (direkt über %command%) und Sunshine/Moonlight (manueller Prozessname).


Inhaltsverzeichnis


Schnellstart

Für Nutzer

Wenn du FocusFix direkt verwenden willst, ist eine fertige FocusFix.exe der empfohlene Weg. Du brauchst dann weder ein Virtual Environment noch ein manuelles pip install.

Steam-Beispiel:

"C:\Path\To\FocusFix\FocusFix.exe" %command%

Mit Debug-Logging:

"C:\Path\To\FocusFix\FocusFix.exe" -debug %command%

Für Entwickler

Wenn du FocusFix aus dem Repository starten oder weiterentwickeln willst:

cd C:\Path\To\FocusFix
py -m pip install -r requirements.txt

Danach kannst du focusfix.py direkt mit deinem Python-Interpreter oder über pythonw.exe verwenden.

Steam-Beispiel für die Quellcode-Nutzung mit lokalem .venv:

"C:\Projekte\FocusFix\.venv\Scripts\pythonw.exe" "C:\Projekte\FocusFix\focusfix.py" %command%

Ohne lokales .venv und mit globalem Python im PATH:

"pythonw.exe" "C:\Projekte\FocusFix\focusfix.py" %command%

Problembeschreibung

Beim Start eines Spiels über Steam oder Sunshine/Moonlight öffnet sich das Spielfenster im Hintergrund. Die Steam-Oberfläche, die Windows-Taskleiste oder andere Fenster verdecken es, und der Spieler muss manuell per Alt+Tab wechseln.

Ursache: Windows vergibt den Vordergrundfokus nur eingeschränkt an Prozesse, die das System als berechtigt ansieht. Zusätzlich erzeugen manche Spiele beim Start mehrere Fenster wie Splashscreens, Launcher oder titellose Overlay-Fenster, die den Fokus stören können.

Lösungsansatz

focusfix.py kann in zwei Modi arbeiten:

  1. Steam-Wrapper-Modus: Das Script erhält %command%, leitet daraus den Prozessnamen ab, startet das Spiel selbst und überwacht anschließend den Fensterfokus.
  2. Direktmodus: Das Script wird mit --process Name gestartet und überwacht einen bekannten Spielprozess.

Das Tool ist nicht auf ein bestimmtes Spiel festgelegt, sondern für viele ähnliche Fokus-Probleme mit vergleichbarem Fensterverhalten gedacht.

Architektur

Steam Launch Options / Sunshine Befehlsvorbereitung
        │
        ▼
   ┌────────────────────┐
   │ pythonw.exe        │
   │ focusfix.py        │
   │                    │
   │ Steam: %command%   │
   │ Sunshine:          │
   │ --process Name     │
   └────────┬───────────┘
            │
   Steam-Modus:
   startet das Spiel selbst
            │
   Prozess/Fenster gefunden
            │
   ┌────────▼───────────┐
   │ 1. Prozess finden  │
   │ 2. Fenster erkennen│
   │ 3. Größe abwarten  │
   │ 4. Spiel fokussieren│
   │ 5. Wechsel beobachten│
   │ 6. Script beendet  │
   └────────────────────┘

Zwei Dateien, davon eine nur noch optional:

Datei Sprache Aufgabe
focusfix.py Python 3 Steam-Wrapper-Modus, Direktmodus per --process, Prozess-Monitoring, Fenstererkennung, Fensterwechsel-Erkennung, Fokus-Erzwingung, Logging
launch.vbs VBScript Legacy-Wrapper für ältere Steam-Konfigurationen; für den aktuellen Ablauf nicht mehr erforderlich

Voraussetzungen

Komponente Version Hinweis
Windows 10 / 11 Benötigt Win32 API (user32.dll)
Steam Beliebig Startoptionen müssen konfigurierbar sein
Python 3.10+ Nur für Quellcode-Nutzung erforderlich
pip-Pakete psutil, pywin32 Nur für Quellcode-Nutzung erforderlich

Direkte Verwendung

Für normale Nutzer ist eine fertige .exe der einfachste Weg.

Aus Quellcode ausführen

cd C:\Path\To\FocusFix
py -m pip install -r requirements.txt

Optional kannst du dafür auch ein Virtual Environment verwenden. Für Entwickler ist das sinnvoll, für Endanwender aber nicht der Standardweg.

Dateistruktur im Repository

C:\Path\To\FocusFix\
├── focusfix.py             # Hauptscript
├── focusfix.log            # Logdatei (nur bei --debug / -debug)
├── launch.vbs              # Legacy-Wrapper, optional
├── requirements.txt        # Python-Abhängigkeiten für Quellcode-Nutzung
├── CLAUDE.md               # Kontext für Claude Code
└── README.md               # Diese Dokumentation

Konfiguration

Steam

  1. Steam öffnen → Bibliothek
  2. Rechtsklick auf das Spiel → Eigenschaften
  3. Unter Allgemein → Startoptionen eine der folgenden Varianten eintragen:

Variante A — Empfohlen für Nutzer: FocusFix.exe

"C:\Path\To\FocusFix\FocusFix.exe" %command%

Mit Debug-Logging:

"C:\Path\To\FocusFix\FocusFix.exe" -debug %command%

Die .exe übernimmt denselben Wrapper-Modus wie focusfix.py: Sie erhält %command%, startet das Spiel und überwacht danach den Fokus. Diese Variante ist für Endanwender gedacht. Die Pfade im Beispiel sind Platzhalter und müssen durch deinen tatsächlichen Installationspfad ersetzt werden.

Variante B — Quellcode direkt mit focusfix.py

"C:\Path\To\Python\pythonw.exe" "C:\Path\To\FocusFix\focusfix.py" %command%

focusfix.py extrahiert den Prozessnamen automatisch aus %command%, startet das eigentliche Spiel und überwacht danach den Fensterfokus. Die gleiche Startoption kann für beliebige Steam-Spiele mit vergleichbarem Fokus-Problem verwendet werden. Die Pfade im Beispiel sind Platzhalter und müssen durch deinen tatsächlichen Installationspfad ersetzt werden.

Erklärung:

  • pythonw.exe — startet Python ohne Konsolenfenster
  • "...\focusfix.py" — Python-Script im Steam-Wrapper-Modus
  • %command% — Steam-Platzhalter, wird zur Laufzeit durch den vollständigen Pfad zur Spiel-Executable ersetzt, z.B. "C:\SteamLibrary\...\Game.exe"

Variante C — Legacy: über launch.vbs

Wenn du den alten VBScript-Wrapper weiterhin verwenden willst, kannst du in Steam Folgendes eintragen:

wscript "C:\Path\To\FocusFix\launch.vbs" %command%
Beispiel: "C:\Projekte\FocusFix\launch.vbs" %command%

Mit Debug-Logging:

wscript "C:\Path\To\FocusFix\launch.vbs" -debug %command%
wscript "C:\Projekte\FocusFix\launch.vbs" -debug %command%

launch.vbs extrahiert den Prozessnamen aus %command%, startet focusfix.py unsichtbar mit --process und startet danach das eigentliche Spiel. -d, -debug und --debug werden an focusfix.py weitergereicht und nicht an das Spiel übergeben. Diese Variante funktioniert weiterhin, ist aber nur noch als Legacy-/Fallback-Weg gedacht, weil focusfix.py den Wrapper-Job inzwischen selbst übernehmen kann. Der Wrapper erwartet focusfix.py relativ zu seinem eigenen Speicherort. Für Python nutzt er zuerst .venv\Scripts\pythonw.exe im selben Ordner und fällt, falls nicht vorhanden, auf pythonw.exe aus der globalen Installation beziehungsweise dem PATH zurück.

Erklärung:

  • wscript — startet VBScript ohne sichtbares Konsolenfenster
  • "...\launch.vbs" — Legacy-Wrapper, der focusfix.py indirekt startet
  • -debug — optional, aktiviert focusfix.log für focusfix.py
  • %command% — Steam-Platzhalter mit dem ursprünglichen Spielstartbefehl

Sunshine / Moonlight

Für Nutzer mit .exe:

"C:\Path\To\FocusFix\FocusFix.exe" --process "Prozessname"

Mit Debug-Logging:

"C:\Path\To\FocusFix\FocusFix.exe" --debug --process "Prozessname"

Für Quellcode-Nutzung in Sunshine als Befehlsvorbereitung (Command Preparation) pro Spiel:

"C:\Path\To\Python\pythonw.exe" "C:\Path\To\FocusFix\focusfix.py" --process "Prozessname"

Den Prozessnamen im Task-Manager ablesen, ohne .exe. Beispiele:

Spiel Prozessname
Crimson Desert CrimsonDesert
Wuthering Waves Client-Win64-Shipping

Wichtig: Wenn du den Quellcode-Weg nutzt, muss der verwendete Python-Interpreter Zugriff auf die installierten Abhängigkeiten aus requirements.txt haben. pythonw.exe ist für unsichtbare Hintergrundausführung sinnvoller als python.exe.

Ablauf zur Laufzeit

Zeitachse
─────────────────────────────────────────────────────────────────────
t=0s    Steam startet das Script mit %command%
        oder Sunshine mit --process "GameName"

t=0.1s  focusfix.py beginnt zu arbeiten
        → Steam-Modus: startet zuerst das Spiel und leitet den Prozessnamen ab
        → Danach: sucht nach Prozess "GameName"

t=~3s   Spielprozess gestartet, ggf. Splashscreen erscheint
        → Script findet den Prozess (PID)
        → Sucht nach Fenster mit Breite >= 800px
        → Kleine Splashscreens werden ignoriert

t=~10s  Hauptfenster des Spiels erscheint
        → Script findet das Fenster
        → Bevorzugt Fenster mit Titel
        → Wartet 3 Sekunden
        → Wartet bis Fenstergröße stabil ist

t=~13s  Phase 3: Fokus-Erzwingung
        → Spielfenster wird in den Vordergrund gebracht
        → Bei Misserfolg: bis zu 15 Wiederholungen mit je 2s Pause
        → Beobachtet Fensterwechsel (z.B. Splash → Hauptfenster)
        → Ignoriert problematische titellose Overlay-Fenster

t=~15s  Erfolg → focusfix.py beendet sich
        → Logdatei enthält den vollständigen Ablauf

Dateireferenz

focusfix.py

Funktionsübersicht

Funktion Beschreibung
derive_process_name(command) Leitet den Prozessnamen aus dem ersten Element eines Spielbefehls ab
launch_game(command) Startet das eigentliche Spiel im Steam-Wrapper-Modus
find_process_pids(name) Sucht laufende Prozesse nach Name (Teilstring, case-insensitiv), gibt PIDs zurück
find_game_window(pids) Findet das Hauptfenster der gegebenen PIDs, bevorzugt Fenster mit Titel und dann nach Größe
wait_for_stable_size(hwnd) Wartet bis die Fenstergröße sich stabilisiert hat
is_foreground(hwnd) Prüft ob ein Fenster aktuell im Vordergrund ist
bring_to_front(hwnd) Erzwingt den Vordergrundfokus für ein Fenster
main() Orchestriert Startmodus, Prozesssuche, Fenstersuche und Fokus-Erzwingung

main() — Ablauf

  1. Startphase: Entweder wird der Prozessname direkt über --process übergeben oder im Steam-Modus aus dem Spielbefehl abgeleitet.
  2. Steam-Wrapper-Modus: Falls ein Spielbefehl übergeben wurde, startet das Script das Spiel selbst.
  3. Phase 1 — Prozess-Suche: Pollt alle 0,5 Sekunden nach dem Prozessnamen. Bricht nach --timeout Sekunden ab.
  4. Phase 2 — Fenster-Suche: Pollt alle 0,5 Sekunden nach einem sichtbaren Fenster mit ausreichender Größe. Nach Fund: 3 Sekunden Wartezeit für die vollständige Initialisierung.
  5. Phase 3 — Fokus mit Fensterwechsel-Erkennung: Bis zu 15 Versuche den Spielfokus zu erzwingen, mit je 2 Sekunden Pause. Beobachtet dabei, ob sich das Fenster ändert und fokussiert das neue Fenster erneut.

launch.vbs

launch.vbs ist nur noch ein Legacy-Wrapper. Die aktuelle empfohlene Nutzung für Endanwender erfolgt über FocusFix.exe. Die Datei kann als Fallback im Repository bleiben, wird für den normalen Ablauf aber nicht mehr benötigt. Der Wrapper löst focusfix.py relativ zu seinem eigenen Ordner auf, verwendet bevorzugt .venv\Scripts\pythonw.exe daneben und fällt sonst auf pythonw.exe aus der globalen Python-Installation beziehungsweise dem PATH zurück. -d/-debug/--debug kann er an focusfix.py weitergeben.

Konfigurationsparameter

Kommandozeilenargumente

Argument Pflicht Standard Beschreibung
--process Nein — Teilstring des Prozessnamens (case-insensitiv, ohne .exe)
--timeout Nein 120 Maximale Wartezeit in Sekunden für Prozess- und Fensterfund
command Nein — Steam-Spielbefehl, z.B. %command%; startet das Spiel und leitet den Prozessnamen automatisch ab

Es muss entweder --process oder ein Spielbefehl übergeben werden.

Konstanten in focusfix.py

Konstante Wert Beschreibung
MIN_WINDOW_WIDTH 800 Mindestbreite in Pixeln, um Splashscreens auszufiltern
FOCUS_RETRIES 15 Maximale Anzahl der Fokus-Versuche
FOCUS_RETRY_DELAY 2.0 Sekunden zwischen Fokus-Versuchen

Relevante Pfade

Pfad Zweck
C:\Path\To\FocusFix\FocusFix.exe Empfohlener Pfad für Endanwender
C:\Path\To\Python\pythonw.exe Beispielpfad zum Python-Interpreter ohne Konsolenfenster, für Quellcode-Nutzung
C:\Path\To\FocusFix\focusfix.py Beispielpfad zum Hauptscript

Bei einer Änderung des Installationsverzeichnisses müssen diese Pfade in den Steam-Startoptionen oder in Sunshine angepasst werden.

Windows API — Technischer Hintergrund

Das SetForegroundWindow-Problem

Seit Windows 2000 verhindert das Betriebssystem, dass beliebige Prozesse den Vordergrundfokus "stehlen" können. SetForegroundWindow(hwnd) funktioniert nur eingeschränkt. Andernfalls blinkt das Fenster lediglich in der Taskleiste.

Da focusfix.py als eigenständiger Prozess läuft und nicht Teil der normalen Spiel-UI ist, erfüllt es diese Bedingungen oft nicht direkt.

Workaround-Strategie

Das Script kombiniert drei Techniken:

1. Alt-Key-Simulation (keybd_event)

Simuliert einen Tastendruck der Alt-Taste. Windows behandelt den aufrufenden Prozess danach eher wie einen Prozess mit Benutzerinteraktion.

2. Thread-Input-Verbindung (AttachThreadInput)

Verbindet die Eingabewarteschlangen zweier Threads. Dadurch kann das Ziel-Fenster zuverlässiger in den Vordergrund gebracht werden.

3. Mehrfache Fokus-Befehle

ShowWindow, BringWindowToTop, SetForegroundWindow, SetFocus und SetActiveWindow adressieren jeweils einen leicht anderen Aspekt des Fenster-Fokus unter Windows.

Splashscreen-Erkennung

Viele Spiele zeigen beim Start einen Splashscreen, bevor das Hauptfenster erscheint. Beide gehören zum selben Prozess.

Das wichtigste Unterscheidungsmerkmal ist hier die Fenstergröße. Kleine Startfenster werden über MIN_WINDOW_WIDTH = 800 aussortiert. Zusätzlich werden Fenster mit Titel bevorzugt, um titellose Overlay-Fenster nicht fälschlich als Hauptfenster zu wählen.

Manuelles Testen

Direktmodus testen

cd C:\Path\To\FocusFix
python focusfix.py --process "CrimsonDesert" --timeout 5

Steam-Wrapper-Modus testen

python focusfix.py "C:\Path\To\Game\TestGame.exe"

Standardmäßig erzeugt FocusFix keine Logdatei. Mit --debug oder -debug landen die Laufzeit-Logs in focusfix.log; bei jedem neuen Scriptstart wird die Datei dabei überschrieben. Bei Ausführung über pythonw.exe gibt es keine sichtbare Ausgabe. Bei manuellen Starts mit python.exe können Argument- oder Interpreter-Fehler weiterhin in der Konsole erscheinen.

Gesamtablauf testen

  1. Steam-Startoptionen wie oben konfigurieren.
  2. Spiel über Steam starten.
  3. Erwartung: Spielfenster erscheint nach dem Ladescreen im Vordergrund, ohne zusätzliches Konsolenfenster.
  4. Falls mit --debug gestartet wurde, focusfix.log prüfen.

Debugging

Für die Fehlersuche FocusFix mit --debug oder -debug starten. Dann werden alle Informationen in focusfix.log protokolliert; ein vorhandenes Logfile aus einem früheren Lauf wird dabei ersetzt:

  • Gefundene Kandidaten-Fenster mit Handle, Titel, Größe und PID
  • Fensterwechsel und ignorierte titellose Fenster
  • Fokus-Versuche mit Ergebnis
  • Fehler mit Traceback

Häufige Probleme

Symptom Ursache Lösung
Spiel startet nicht Steam-Startoptionen fehlerhaft Prüfen ob %command% am Ende steht und .exe oder pythonw.exe/focusfix.py korrekt referenziert werden
ModuleNotFoundError: psutil Falsche Python-Installation py -m pip install -r requirements.txt ausführen oder den richtigen Python-Interpreter verwenden
Script findet Prozess nicht Prozessname stimmt nicht oder Launcher-Kette ist ungewöhnlich Mit --process testen oder Log prüfen
Fenster wird nicht fokussiert Windows-Restriktion zu streng Retry-Anzahl/Delay in Konstanten erhöhen
Alt-Taste bleibt hängen Spiel mit Admin-Rechten, Script ohne Script ebenfalls als Admin starten
CMD-Fenster sichtbar python.exe statt pythonw.exe Steam-/Sunshine-Konfiguration prüfen oder .exe verwenden
Verdunkeltes/blockiertes Spiel Titelloses Overlay-Fenster Log prüfen; sollte meist durch Fenster-mit-Titel-Bevorzugung abgefangen werden

Fenster-Inspektion per PowerShell

Get-Process -Name GameName | Select-Object Id, Name, MainWindowTitle, MainWindowHandle

Bekannte Einschränkungen

  • Kein Admin erforderlich, aber manche Spiele starten mit erhöhten Rechten. Dann muss das Script ebenfalls als Admin laufen.
  • Exklusiver Vollbildmodus: Spiele im exklusiven Vollbild können sich anders verhalten.
  • Anti-Cheat: Manche Anti-Cheat-Systeme könnten Eingabesimulation oder Fokus-Workarounds blockieren.
  • Mehrere Monitore: find_game_window wählt das Fenster unabhängig vom Monitor.
  • Nicht universell für jedes Spiel: Das Tool ist generisch für viele ähnliche Fälle, aber nicht garantiert für jeden Launcher, jedes Anti-Cheat-System oder jedes ungewöhnliche Fenster-/Startverhalten.
S
Description
No description provided
Readme
101 KiB
Latest
2026-04-18 17:16:37 +02:00
Languages
Python 87.1%
VBScript 12.9%