diff --git a/src/PSLauncher.App/App.xaml.cs b/src/PSLauncher.App/App.xaml.cs
index 26a2c9b..dcd5326 100644
--- a/src/PSLauncher.App/App.xaml.cs
+++ b/src/PSLauncher.App/App.xaml.cs
@@ -120,6 +120,19 @@ public partial class App : Application
Log.Information("PSLauncher starting (logs in {Path})", LogsDirectory);
+ // RENDER MODE : sur certains environnements (RDP, VMs sans hardware accel,
+ // GPU émulé, Intel HD anciens, Windows Server sans Desktop Experience…)
+ // l'accélération matérielle WPF plante en silence : la fenêtre s'affiche
+ // toute blanche, aucun contenu ne rend, aucune exception ne remonte. C'est
+ // un bug classique non rattrapable côté .NET parce que le pipeline graphique
+ // tombe entre les mailles du try/catch. On force le rendu software dans 3 cas :
+ // 1. RenderCapability.Tier == 0 (WPF lui-même détecte aucune accel possible)
+ // 2. Session Bureau à distance (RDP) détectée
+ // 3. Var d'env PSLAUNCHER_SOFTWARE_RENDER=1 (override manuel pour debug)
+ // Trade-off : rendu software plus lent (~30% impact sur le scrolling de la
+ // liste des versions), mais au moins ça affiche QUELQUE CHOSE.
+ ApplyRenderModeFallback();
+
AppDomain.CurrentDomain.UnhandledException += (_, args) =>
{
// CRITIQUE : on flush AVANT que le process meure. Sans ça, sur les
@@ -317,6 +330,55 @@ public partial class App : Application
window.Show();
}
+ ///
+ /// Décide entre rendu hardware (par défaut WPF) et rendu software, en fonction
+ /// de l'environnement détecté + override par variable d'environnement. Log
+ /// la décision pour faciliter le debug si l'utilisateur reporte un écran blanc.
+ ///
+ private static void ApplyRenderModeFallback()
+ {
+ try
+ {
+ // Override manuel : PSLAUNCHER_SOFTWARE_RENDER=1 force le software.
+ // Le user peut le set dans les variables d'environnement Windows OU dans
+ // le raccourci .lnk (champ Cible : "cmd /c set PSLAUNCHER_SOFTWARE_RENDER=1 && start PS_Launcher.exe")
+ var envOverride = Environment.GetEnvironmentVariable("PSLAUNCHER_SOFTWARE_RENDER");
+ var manualSoftware = !string.IsNullOrEmpty(envOverride)
+ && (envOverride == "1" || envOverride.Equals("true", StringComparison.OrdinalIgnoreCase));
+
+ // RenderCapability.Tier renvoie un int packed : (tier << 16). Tier 0 = pas
+ // d'accélération matérielle possible. Tier 1 = partielle. Tier 2 = complète.
+ var tier = System.Windows.Media.RenderCapability.Tier >> 16;
+
+ // GetSystemMetrics(SM_REMOTESESSION) = 1 si la session est une session RDP.
+ // SM_REMOTESESSION constant = 0x1000 (4096).
+ var isRdp = GetSystemMetrics(0x1000) != 0;
+
+ var shouldUseSoftware = manualSoftware || tier == 0 || isRdp;
+
+ Log.Information("Render env : Tier={Tier} RDP={Rdp} EnvOverride={EnvOverride} → SoftwareOnly={Sw}",
+ tier, isRdp, manualSoftware, shouldUseSoftware);
+
+ if (shouldUseSoftware)
+ {
+ System.Windows.Media.RenderOptions.ProcessRenderMode =
+ System.Windows.Interop.RenderMode.SoftwareOnly;
+ Log.Warning("WPF render mode forced to SoftwareOnly (cause: " +
+ (manualSoftware ? "env override" : tier == 0 ? "Tier=0 no GPU accel" : "RDP session") + ")");
+ }
+ }
+ catch (Exception ex)
+ {
+ // Pas critique : si le fallback échoue, on continue avec le default
+ // hardware accel et on espère que ça marche. Le user verra un écran
+ // blanc si non, mais au moins l'app aura pas crashé.
+ Log.Warning(ex, "Failed to evaluate render-mode fallback, keeping default");
+ }
+ }
+
+ [DllImport("user32.dll")]
+ private static extern int GetSystemMetrics(int nIndex);
+
protected override void OnExit(ExitEventArgs e)
{
Log.Information("PSLauncher shutting down");
diff --git a/src/PSLauncher.App/PSLauncher.App.csproj b/src/PSLauncher.App/PSLauncher.App.csproj
index 72c37ed..11f59dd 100644
--- a/src/PSLauncher.App/PSLauncher.App.csproj
+++ b/src/PSLauncher.App/PSLauncher.App.csproj
@@ -18,9 +18,9 @@
PROSERVE Launcher
© 2026 ASTERION VR — All rights reserved
PSLauncher.App
- 1.0.2
- 1.0.2.0
- 1.0.2.0
+ 1.0.3
+ 1.0.3.0
+ 1.0.3.0
true
@@ -47,7 +47,7 @@
Le runtime est pré-installé sur Win11 et auto-mis-à-jour via Windows
Update sur Win10 récent. Si absent, le contrôle affiche une erreur
et on aiguille l'user vers https://go.microsoft.com/fwlink/p/?LinkId=2124703 -->
-
+