LaunchVersion: restore launcher window when Proserve exits

After clicking Lancer, the launcher minimizes to the taskbar so Proserve
has the foreground. Add an Exited event handler on the launched Process
that brings the launcher back from the taskbar once the game closes.

EnableRaisingEvents is required (false by default) to receive Exited.
The handler runs on a worker thread so we marshal back to the UI via
Dispatcher.Invoke before touching WindowState. A brief Topmost=true /
false toggle nudges the window to the foreground without permanently
locking it on top.

Wrapped in try/catch — some ShellExecute spawns return a Process with
limited access (no event support), in which case we just log and let
the user click the taskbar icon manually.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-02 12:41:54 +02:00
parent 8988d130ac
commit 7a12153343

View File

@@ -424,13 +424,41 @@ public sealed partial class MainViewModel : ObservableObject
if (row.Installed is null) return; if (row.Installed is null) return;
try try
{ {
_processLauncher.Launch(row.Installed); var proc = _processLauncher.Launch(row.Installed);
_config.LastLaunchedVersion = row.Version; _config.LastLaunchedVersion = row.Version;
_configStore.Save(_config); _configStore.Save(_config);
// Réduit la fenêtre du launcher pour ne pas gêner Proserve qui démarre // Réduit la fenêtre du launcher pour ne pas gêner Proserve qui démarre
if (Application.Current.MainWindow is { } mw) if (Application.Current.MainWindow is { } mw)
mw.WindowState = WindowState.Minimized; mw.WindowState = WindowState.Minimized;
// Quand Proserve se termine, on remet la fenêtre du launcher au premier plan.
// EnableRaisingEvents est requis pour recevoir l'event Exited.
try
{
proc.EnableRaisingEvents = true;
proc.Exited += (_, _) =>
{
_logger.LogInformation("Proserve v{Version} a quitté — restauration du launcher", row.Version);
Application.Current?.Dispatcher.Invoke(() =>
{
if (Application.Current.MainWindow is { } main)
{
if (main.WindowState == WindowState.Minimized)
main.WindowState = WindowState.Normal;
main.Activate();
// Pop temporaire pour amener la fenêtre au premier plan
main.Topmost = true;
main.Topmost = false;
}
});
};
}
catch (Exception ex)
{
// ShellExecute peut renvoyer un Process sans accès aux events — non bloquant
_logger.LogDebug(ex, "Could not hook Exited on launched process");
}
} }
catch (Exception ex) catch (Exception ex)
{ {