Compare commits
3 Commits
a6ea9b11af
...
8d8cf32e12
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d8cf32e12 | |||
| e2d9171df1 | |||
| 5b489dcfc5 |
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#define MyAppName "PROSERVE Launcher"
|
#define MyAppName "PROSERVE Launcher"
|
||||||
#define MyAppShortName "PS_Launcher"
|
#define MyAppShortName "PS_Launcher"
|
||||||
#define MyAppVersion "1.0.2"
|
#define MyAppVersion "1.0.3"
|
||||||
#define MyAppPublisher "ASTERION VR"
|
#define MyAppPublisher "ASTERION VR"
|
||||||
#define MyAppURL "https://asterionvr.com"
|
#define MyAppURL "https://asterionvr.com"
|
||||||
#define MyAppExeName "PS_Launcher.exe"
|
#define MyAppExeName "PS_Launcher.exe"
|
||||||
@@ -65,6 +65,14 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription
|
|||||||
Source: "..\src\PSLauncher.App\bin\Release\net8.0-windows10.0.17763.0\win-x64\publish\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "..\src\PSLauncher.App\bin\Release\net8.0-windows10.0.17763.0\win-x64\publish\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: "..\src\PSLauncher.Updater\bin\Release\net8.0-windows\win-x64\publish\{#MyUpdaterExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "..\src\PSLauncher.Updater\bin\Release\net8.0-windows\win-x64\publish\{#MyUpdaterExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: "..\docs\PS_Launcher-Guide-Utilisateur.pptx"; DestDir: "{app}\docs"; Flags: ignoreversion
|
Source: "..\docs\PS_Launcher-Guide-Utilisateur.pptx"; DestDir: "{app}\docs"; Flags: ignoreversion
|
||||||
|
; WebView2 Evergreen Bootstrapper (Microsoft, redistribuable). 1.6 MB.
|
||||||
|
; Téléchargé depuis https://go.microsoft.com/fwlink/p/?LinkId=2124703
|
||||||
|
; Exécuté en silencieux à l'install SI WebView2 Runtime n'est pas déjà présent
|
||||||
|
; (vérification registre via la fonction Pascal IsWebView2Installed ci-dessous).
|
||||||
|
; Sans ça, sur un Win10/Server sans WebView2 préinstallé, la fenêtre du launcher
|
||||||
|
; reste toute blanche au démarrage parce que les contrôles WebView2 (Reports +
|
||||||
|
; Documentation) ne peuvent pas s'initialiser et plantent en silence le rendu UI.
|
||||||
|
Source: "redists\MicrosoftEdgeWebview2Setup.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall; Check: not IsWebView2Installed
|
||||||
|
|
||||||
[Icons]
|
[Icons]
|
||||||
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
||||||
@@ -73,6 +81,14 @@ Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
|
|||||||
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
||||||
|
|
||||||
[Run]
|
[Run]
|
||||||
|
; Installe WebView2 Runtime si pas déjà présent. /silent /install = install
|
||||||
|
; non-interactif. Le bootstrapper télécharge ~150 MB depuis Microsoft (1-2 min
|
||||||
|
; selon la connexion). StatusMsg pour que l'utilisateur voie ce qu'il se passe.
|
||||||
|
; Code exit attendu : 0 (déjà installé OU install réussie). On ne fail pas le
|
||||||
|
; setup global même si ça échoue — le launcher logue ensuite l'absence si ça
|
||||||
|
; pose problème, plutôt que de bloquer toute l'installation pour ça.
|
||||||
|
Filename: "{tmp}\MicrosoftEdgeWebview2Setup.exe"; Parameters: "/silent /install"; StatusMsg: "Installation du composant Microsoft Edge WebView2 Runtime (~150 MB, peut prendre 1-2 min)..."; Check: not IsWebView2Installed; Flags: waituntilterminated
|
||||||
|
|
||||||
; Règles firewall pour le cache LAN P2P. Profile=private,domain (PAS public) =
|
; Règles firewall pour le cache LAN P2P. Profile=private,domain (PAS public) =
|
||||||
; safety net : même si l'utilisateur connecte le PC à un Wi-Fi public, le port
|
; safety net : même si l'utilisateur connecte le PC à un Wi-Fi public, le port
|
||||||
; reste fermé. Le filtre RFC1918 dans LanCacheServer.cs est la première barrière,
|
; reste fermé. Le filtre RFC1918 dans LanCacheServer.cs est la première barrière,
|
||||||
@@ -92,3 +108,28 @@ Filename: "{sys}\netsh.exe"; Parameters: "advfirewall firewall delete rule name=
|
|||||||
; binaires installés et le dossier d'install s'il est vide après.
|
; binaires installés et le dossier d'install s'il est vide après.
|
||||||
Type: filesandordirs; Name: "{app}\*.bak"
|
Type: filesandordirs; Name: "{app}\*.bak"
|
||||||
Type: dirifempty; Name: "{app}"
|
Type: dirifempty; Name: "{app}"
|
||||||
|
|
||||||
|
[Code]
|
||||||
|
// Détecte si Microsoft Edge WebView2 Runtime est déjà installé sur le système.
|
||||||
|
// Référence : https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution
|
||||||
|
//
|
||||||
|
// 3 emplacements registre possibles selon le contexte d'install du runtime :
|
||||||
|
// - HKLM 64-bit (machine-wide, install par admin)
|
||||||
|
// - HKLM 32-bit (machine-wide, parfois utilisé par les versions plus anciennes)
|
||||||
|
// - HKCU (user-only, install par utilisateur sans admin)
|
||||||
|
//
|
||||||
|
// La clé contient une valeur 'pv' avec la version installée. Présence non vide
|
||||||
|
// = runtime présent. Le check Edge classique (HKLM\...\Edge\BLBeacon) ne suffit
|
||||||
|
// pas parce qu'Edge stable ≠ WebView2 Runtime (deux composants distincts).
|
||||||
|
function IsWebView2Installed(): Boolean;
|
||||||
|
var
|
||||||
|
PV: String;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
if RegQueryStringValue(HKLM, 'SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}', 'pv', PV) and (PV <> '') and (PV <> '0.0.0.0') then
|
||||||
|
Result := True
|
||||||
|
else if RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}', 'pv', PV) and (PV <> '') and (PV <> '0.0.0.0') then
|
||||||
|
Result := True
|
||||||
|
else if RegQueryStringValue(HKCU, 'Software\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}', 'pv', PV) and (PV <> '') and (PV <> '0.0.0.0') then
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|||||||
BIN
installer/redists/MicrosoftEdgeWebview2Setup.exe
Normal file
BIN
installer/redists/MicrosoftEdgeWebview2Setup.exe
Normal file
Binary file not shown.
@@ -120,6 +120,19 @@ public partial class App : Application
|
|||||||
|
|
||||||
Log.Information("PSLauncher starting (logs in {Path})", LogsDirectory);
|
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) =>
|
AppDomain.CurrentDomain.UnhandledException += (_, args) =>
|
||||||
{
|
{
|
||||||
// CRITIQUE : on flush AVANT que le process meure. Sans ça, sur les
|
// CRITIQUE : on flush AVANT que le process meure. Sans ça, sur les
|
||||||
@@ -317,6 +330,55 @@ public partial class App : Application
|
|||||||
window.Show();
|
window.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
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)
|
protected override void OnExit(ExitEventArgs e)
|
||||||
{
|
{
|
||||||
Log.Information("PSLauncher shutting down");
|
Log.Information("PSLauncher shutting down");
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
<Product>PROSERVE Launcher</Product>
|
<Product>PROSERVE Launcher</Product>
|
||||||
<Copyright>© 2026 ASTERION VR — All rights reserved</Copyright>
|
<Copyright>© 2026 ASTERION VR — All rights reserved</Copyright>
|
||||||
<RootNamespace>PSLauncher.App</RootNamespace>
|
<RootNamespace>PSLauncher.App</RootNamespace>
|
||||||
<Version>1.0.2</Version>
|
<Version>1.0.3</Version>
|
||||||
<AssemblyVersion>1.0.2.0</AssemblyVersion>
|
<AssemblyVersion>1.0.3.0</AssemblyVersion>
|
||||||
<FileVersion>1.0.2.0</FileVersion>
|
<FileVersion>1.0.3.0</FileVersion>
|
||||||
|
|
||||||
<!-- Single-file self-contained publish profile (used by `dotnet publish`) -->
|
<!-- Single-file self-contained publish profile (used by `dotnet publish`) -->
|
||||||
<PublishSingleFile>true</PublishSingleFile>
|
<PublishSingleFile>true</PublishSingleFile>
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
Le runtime est pré-installé sur Win11 et auto-mis-à-jour via Windows
|
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
|
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 -->
|
et on aiguille l'user vers https://go.microsoft.com/fwlink/p/?LinkId=2124703 -->
|
||||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2792.45" />
|
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.3800.47" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user