v0.14.0 — rename PSLauncher.exe → PS_Launcher.exe (with backward compat)

Aligns the executable name with the repo / product naming. Backward-
compatible: existing installs that have PSLauncher.exe on disk continue
to work — the self-updater overwrites the file at the running .exe path
without renaming, so the historical filename persists on those machines.

Changes
- AssemblyName : PSLauncher → PS_Launcher (both App and Updater csproj)
- Inno Setup : MyAppExeName, MyUpdaterExeName, OutputBaseFilename all
  now use PS_Launcher prefix
- LauncherSelfUpdater : looks for PS_Launcher.Updater.exe first, falls
  back to legacy PSLauncher.Updater.exe so old installs keep updating
- Build scripts (build-launcher / build-updater / build-installer /
  build-all) : taskkill both legacy AND new names; output paths printed
  with new names
- .gitignore : added PS_Launcher.exe / PS_Launcher.Updater.exe /
  PS_Launcher-*.exe patterns alongside the legacy ones; also ignored
  the WebView2 user-data folder and Office ~$ lock files
- Server admin/launcher.php : URL pattern now generates
  PS_Launcher-{ver}.exe ; SignManifest's existing tolerant glob
  *{ver}*.exe still matches both names
- Versions bumped to 0.14.0 (App + Updater + installer .iss)

Migration story for clients
- Brand-new install via PS_Launcher-Setup-0.14.0.exe → PS_Launcher.exe
  on disk
- Existing install (PSLauncher.exe) auto-updates to v0.14 → file stays
  named PSLauncher.exe but contains v0.14 code; self-updater fallback
  ensures future updates keep working

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-03 09:55:41 +02:00
parent 64fbda0191
commit ce3979d131
10 changed files with 100 additions and 50 deletions

13
.gitignore vendored
View File

@@ -53,10 +53,23 @@ server/builds/*
.claude/ .claude/
# Binaires copiés par le post-publish à la racine du repo # Binaires copiés par le post-publish à la racine du repo
# (legacy : PSLauncher.exe — pre-v0.14 ; nouveau : PS_Launcher.exe — depuis v0.14)
/PSLauncher.exe /PSLauncher.exe
/PSLauncher.Updater.exe /PSLauncher.Updater.exe
/PSLauncher-*.exe /PSLauncher-*.exe
/PSLauncher*.bak /PSLauncher*.bak
/PS_Launcher.exe
/PS_Launcher.Updater.exe
/PS_Launcher-*.exe
/PS_Launcher*.bak
# Sortie de l'installeur Inno Setup # Sortie de l'installeur Inno Setup
/installer/output/ /installer/output/
# WebView2 user data folder créé à côté de l'exe au runtime (cache, cookies,
# sync data Edge Chromium). Peut faire plusieurs Mo.
/PSLauncher.exe.WebView2/
/PS_Launcher.exe.WebView2/
# Fichiers de lock Office (Word/PowerPoint) commençant par ~$
~$*

View File

@@ -6,8 +6,10 @@ setlocal
set "REPO=%~dp0" set "REPO=%~dp0"
echo. echo.
echo ==^> Termine les eventuelles instances qui verrouilleraient les .exe echo ==^> Termine les eventuelles instances qui verrouilleraient les .exe
taskkill /F /IM PSLauncher.exe /T >nul 2>&1 taskkill /F /IM PSLauncher.exe /T >nul 2>&1
taskkill /F /IM PSLauncher.Updater.exe /T >nul 2>&1 taskkill /F /IM PSLauncher.Updater.exe /T >nul 2>&1
taskkill /F /IM PS_Launcher.exe /T >nul 2>&1
taskkill /F /IM PS_Launcher.Updater.exe /T >nul 2>&1
echo. echo.
echo ==^> dotnet publish PSLauncher.App (Release single-file) echo ==^> dotnet publish PSLauncher.App (Release single-file)
echo. echo.
@@ -22,8 +24,8 @@ if %ERRORLEVEL% NEQ 0 goto :fail
echo. echo.
echo [OK] Les deux exes sont disponibles a la racine du repo : echo [OK] Les deux exes sont disponibles a la racine du repo :
echo %REPO%PSLauncher.exe echo %REPO%PS_Launcher.exe
echo %REPO%PSLauncher.Updater.exe echo %REPO%PS_Launcher.Updater.exe
echo. echo.
pause pause
endlocal & exit /b 0 endlocal & exit /b 0

View File

@@ -13,8 +13,11 @@ setlocal
set "SCRIPT_DIR=%~dp0" set "SCRIPT_DIR=%~dp0"
REM Termine les eventuelles instances en cours qui verrouilleraient les .exe REM Termine les eventuelles instances en cours qui verrouilleraient les .exe
taskkill /F /IM PSLauncher.exe /T >nul 2>&1 REM (les deux noms : legacy PSLauncher et nouveau PS_Launcher >= v0.14.0)
taskkill /F /IM PSLauncher.Updater.exe /T >nul 2>&1 taskkill /F /IM PSLauncher.exe /T >nul 2>&1
taskkill /F /IM PSLauncher.Updater.exe /T >nul 2>&1
taskkill /F /IM PS_Launcher.exe /T >nul 2>&1
taskkill /F /IM PS_Launcher.Updater.exe /T >nul 2>&1
powershell -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%installer\build-installer.ps1" %* powershell -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%installer\build-installer.ps1" %*
set "EXITCODE=%ERRORLEVEL%" set "EXITCODE=%ERRORLEVEL%"

View File

@@ -1,13 +1,17 @@
@echo off @echo off
REM Build du launcher principal (PSLauncher.exe). REM Build du launcher principal (PS_Launcher.exe).
REM Sortie : C:\ASTERION\GIT\PS_Launcher\PSLauncher.exe (~78 Mo single-file self-contained) REM Sortie : C:\ASTERION\GIT\PS_Launcher\PS_Launcher.exe (~78 Mo single-file self-contained)
REM Renommé v0.14.0 : avant c'etait PSLauncher.exe. On taskkill les deux noms
REM pour gerer les deux generations d'install (legacy + nouvelle).
setlocal setlocal
set "REPO=%~dp0" set "REPO=%~dp0"
echo. echo.
echo ==^> Termine les eventuelles instances de PSLauncher qui verrouilleraient les .exe echo ==^> Termine les eventuelles instances de PSLauncher / PS_Launcher qui verrouilleraient les .exe
taskkill /F /IM PSLauncher.exe /T >nul 2>&1 taskkill /F /IM PSLauncher.exe /T >nul 2>&1
taskkill /F /IM PSLauncher.Updater.exe /T >nul 2>&1 taskkill /F /IM PSLauncher.Updater.exe /T >nul 2>&1
taskkill /F /IM PS_Launcher.exe /T >nul 2>&1
taskkill /F /IM PS_Launcher.Updater.exe /T >nul 2>&1
echo. echo.
echo ==^> dotnet publish PSLauncher.App (Release single-file) echo ==^> dotnet publish PSLauncher.App (Release single-file)
echo. echo.
@@ -19,9 +23,9 @@ echo.
if %EXITCODE% NEQ 0 ( if %EXITCODE% NEQ 0 (
echo [ECHEC] Build du launcher echoue avec le code %EXITCODE%. echo [ECHEC] Build du launcher echoue avec le code %EXITCODE%.
) else ( ) else (
echo [OK] PSLauncher.exe disponible a la racine du repo : echo [OK] PS_Launcher.exe disponible a la racine du repo :
echo %REPO%PSLauncher.exe echo %REPO%PS_Launcher.exe
) )
echo. echo.
pause pause
endlocal & exit /b %EXITCODE% endlocal ^& exit /b %EXITCODE%

View File

@@ -1,14 +1,16 @@
@echo off @echo off
REM Build de l'updater (PSLauncher.Updater.exe). REM Build de l'updater (PS_Launcher.Updater.exe — renomme depuis PSLauncher.Updater.exe en v0.14.0).
REM Sortie : C:\ASTERION\GIT\PS_Launcher\PSLauncher.Updater.exe (~34 Mo single-file) REM Sortie : C:\ASTERION\GIT\PS_Launcher\PS_Launcher.Updater.exe (~34 Mo single-file)
REM L'updater accompagne PSLauncher.exe — il doit etre dans le meme dossier. REM L'updater accompagne PS_Launcher.exe — il doit etre dans le meme dossier.
setlocal setlocal
set "REPO=%~dp0" set "REPO=%~dp0"
echo. echo.
echo ==^> Termine les eventuelles instances qui verrouilleraient les .exe echo ==^> Termine les eventuelles instances qui verrouilleraient les .exe
taskkill /F /IM PSLauncher.exe /T >nul 2>&1 taskkill /F /IM PSLauncher.exe /T >nul 2>&1
taskkill /F /IM PSLauncher.Updater.exe /T >nul 2>&1 taskkill /F /IM PSLauncher.Updater.exe /T >nul 2>&1
taskkill /F /IM PS_Launcher.exe /T >nul 2>&1
taskkill /F /IM PS_Launcher.Updater.exe /T >nul 2>&1
echo. echo.
echo ==^> dotnet publish PSLauncher.Updater (Release single-file) echo ==^> dotnet publish PSLauncher.Updater (Release single-file)
echo. echo.
@@ -20,9 +22,9 @@ echo.
if %EXITCODE% NEQ 0 ( if %EXITCODE% NEQ 0 (
echo [ECHEC] Build de l'updater echoue avec le code %EXITCODE%. echo [ECHEC] Build de l'updater echoue avec le code %EXITCODE%.
) else ( ) else (
echo [OK] PSLauncher.Updater.exe disponible a la racine du repo : echo [OK] PS_Launcher.Updater.exe disponible a la racine du repo :
echo %REPO%PSLauncher.Updater.exe echo %REPO%PS_Launcher.Updater.exe
) )
echo. echo.
pause pause
endlocal & exit /b %EXITCODE% endlocal ^& exit /b %EXITCODE%

View File

@@ -4,18 +4,22 @@
; "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" PSLauncher.iss ; "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" PSLauncher.iss
; ;
; Avant compile : ; Avant compile :
; 1. Faire `dotnet publish src/PSLauncher.App -c Release` (génère PSLauncher.exe ~77 Mo) ; 1. Faire `dotnet publish src/PSLauncher.App -c Release` (génère PS_Launcher.exe ~77 Mo)
; 2. Faire `dotnet publish src/PSLauncher.Updater -c Release` (génère PSLauncher.Updater.exe ~10 Mo) ; 2. Faire `dotnet publish src/PSLauncher.Updater -c Release` (génère PS_Launcher.Updater.exe ~10 Mo)
; ;
; Le script picore directement les binaires dans bin/Release/.../publish/. ; Le script picore directement les binaires dans bin/Release/.../publish/.
#define MyAppName "PROSERVE Launcher" #define MyAppName "PROSERVE Launcher"
#define MyAppShortName "PSLauncher" #define MyAppShortName "PS_Launcher"
#define MyAppVersion "0.13.0" #define MyAppVersion "0.14.0"
#define MyAppPublisher "ASTERION VR" #define MyAppPublisher "ASTERION VR"
#define MyAppURL "https://asterionvr.com" #define MyAppURL "https://asterionvr.com"
#define MyAppExeName "PSLauncher.exe" ; Renommé en v0.14.0 (PSLauncher.exe → PS_Launcher.exe). Les nouvelles installs
#define MyUpdaterExeName "PSLauncher.Updater.exe" ; auront ce nom ; les anciennes installs auto-updatées garderont PSLauncher.exe
; sur disque (le self-updater écrase le fichier sans le renommer). Code OK pour
; les deux variantes.
#define MyAppExeName "PS_Launcher.exe"
#define MyUpdaterExeName "PS_Launcher.Updater.exe"
[Setup] [Setup]
; AppId est UNIQUE pour PSLauncher — ne pas changer entre deux versions sinon ; AppId est UNIQUE pour PSLauncher — ne pas changer entre deux versions sinon
@@ -29,12 +33,12 @@ AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL} AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL} AppUpdatesURL={#MyAppURL}
; Installation user-mode (pas d'admin requis) : le launcher pourra se mettre à jour ; Installation user-mode (pas d'admin requis) : le launcher pourra se mettre à jour
; tout seul via PSLauncher.Updater.exe sans déclencher de UAC. ; tout seul via PS_Launcher.Updater.exe sans déclencher de UAC.
DefaultDirName={localappdata}\Programs\{#MyAppPublisher}\{#MyAppShortName} DefaultDirName={localappdata}\Programs\{#MyAppPublisher}\{#MyAppShortName}
DefaultGroupName={#MyAppName} DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes DisableProgramGroupPage=yes
OutputDir=output OutputDir=output
OutputBaseFilename=PSLauncher-Setup-{#MyAppVersion} OutputBaseFilename=PS_Launcher-Setup-{#MyAppVersion}
SetupIconFile=..\src\PSLauncher.App\Resources\favicon.ico SetupIconFile=..\src\PSLauncher.App\Resources\favicon.ico
Compression=lzma2/ultra Compression=lzma2/ultra
SolidCompression=yes SolidCompression=yes

View File

@@ -53,14 +53,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
'version' => $lver, 'version' => $lver,
'minRequired' => $lmin !== '' ? $lmin : '0.5.0', 'minRequired' => $lmin !== '' ? $lmin : '0.5.0',
'download' => [ 'download' => [
'url' => "{$base}/builds/launcher/PSLauncher-{$lver}.exe", 'url' => "{$base}/builds/launcher/PS_Launcher-{$lver}.exe",
'sizeBytes' => 0, 'sizeBytes' => 0,
'sha256' => 'REPLACE_AFTER_BUILD', 'sha256' => 'REPLACE_AFTER_BUILD',
], ],
'releaseNotesUrl' => null, 'releaseNotesUrl' => null,
]; ];
saveManifest($manifestPath, $manifest); saveManifest($manifestPath, $manifest);
$message = "Section launcher mise à jour (v{$lver}). Upload PSLauncher-{$lver}.exe dans builds/launcher/ puis clique « Hasher le launcher + signer »."; $message = "Section launcher mise à jour (v{$lver}). Upload PS_Launcher-{$lver}.exe dans builds/launcher/ puis clique « Hasher le launcher + signer ».";
} }
elseif ($action === 'remove_launcher') { elseif ($action === 'remove_launcher') {
unset($manifest['launcher']); unset($manifest['launcher']);
@@ -130,7 +130,7 @@ Layout::header('Launcher', 'launcher');
<ol class="muted"> <ol class="muted">
<li>Remplis le formulaire <strong>Définir / mettre à jour</strong> ci-dessous (ex : <code>0.6.0</code>).</li> <li>Remplis le formulaire <strong>Définir / mettre à jour</strong> ci-dessous (ex : <code>0.6.0</code>).</li>
<li>Sur ton poste : <code>dotnet publish src\PSLauncher.App -c Release</code> et <code>dotnet publish src\PSLauncher.Updater -c Release</code> (les exes sont copiés à la racine du repo).</li> <li>Sur ton poste : <code>dotnet publish src\PSLauncher.App -c Release</code> et <code>dotnet publish src\PSLauncher.Updater -c Release</code> (les exes sont copiés à la racine du repo).</li>
<li>Renomme la copie : <code>PSLauncher.exe → PSLauncher-X.Y.Z.exe</code>.</li> <li>Renomme la copie : <code>PS_Launcher.exe → PS_Launcher-X.Y.Z.exe</code> (v0.14+ ; ancien nom <code>PSLauncher.exe</code> reste accepté côté serveur via le glob <code>*{ver}*.exe</code>).</li>
<li>Upload via SFTP dans <code>www/PS_Launcher/builds/launcher/</code>.</li> <li>Upload via SFTP dans <code>www/PS_Launcher/builds/launcher/</code>.</li>
<li>Clique <strong>🔁 Hasher le launcher + signer</strong>.</li> <li>Clique <strong>🔁 Hasher le launcher + signer</strong>.</li>
<li>Les launchers déjà déployés détecteront la nouvelle version au prochain « Vérifier les MAJ ».</li> <li>Les launchers déjà déployés détecteront la nouvelle version au prochain « Vérifier les MAJ ».</li>

View File

@@ -10,14 +10,19 @@
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<ApplicationIcon>Resources\favicon.ico</ApplicationIcon> <ApplicationIcon>Resources\favicon.ico</ApplicationIcon>
<AssemblyName>PSLauncher</AssemblyName> <!-- AssemblyName définit le nom du .exe en sortie. Renommé en v0.14.0 :
PSLauncher.exe → PS_Launcher.exe pour s'aligner sur le nom du repo
et du produit. Les anciens installs (qui ont PSLauncher.exe) gardent
leur nom de fichier après auto-update : le self-updater écrase le
fichier au path courant sans le renommer. Le code reste rétro-compatible. -->
<AssemblyName>PS_Launcher</AssemblyName>
<Company>ASTERION VR</Company> <Company>ASTERION VR</Company>
<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>0.13.0</Version> <Version>0.14.0</Version>
<AssemblyVersion>0.13.0.0</AssemblyVersion> <AssemblyVersion>0.14.0.0</AssemblyVersion>
<FileVersion>0.13.0.0</FileVersion> <FileVersion>0.14.0.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>
@@ -60,7 +65,7 @@
</ItemGroup> </ItemGroup>
<!-- Après chaque `dotnet publish -c Release`, copie le single-file exe à la racine du repo <!-- Après chaque `dotnet publish -c Release`, copie le single-file exe à la racine du repo
(C:\ASTERION\GIT\PS_Launcher\PSLauncher.exe). ContinueOnError pour ne pas casser le (C:\ASTERION\GIT\PS_Launcher\PS_Launcher.exe). ContinueOnError pour ne pas casser le
publish si une instance du launcher tourne et verrouille la cible — l'opérateur peut publish si une instance du launcher tourne et verrouille la cible — l'opérateur peut
killer et réessayer, ou simplement utiliser le binaire depuis bin\Release\... --> killer et réessayer, ou simplement utiliser le binaire depuis bin\Release\... -->
<Target Name="CopyPublishedToRepoRoot" AfterTargets="Publish" <Target Name="CopyPublishedToRepoRoot" AfterTargets="Publish"

View File

@@ -44,7 +44,11 @@ public sealed class LauncherSelfUpdater : ILauncherSelfUpdater
IProgress<DownloadProgress>? progress, IProgress<DownloadProgress>? progress,
CancellationToken ct) CancellationToken ct)
{ {
// 1. Localise le PSLauncher.exe en cours d'exécution // 1. Localise le launcher en cours d'exécution. Le nom du fichier peut varier
// selon l'install : PS_Launcher.exe (nouvelles installs >= v0.14.0) OU
// PSLauncher.exe (anciennes installs auto-updatées qui ont gardé leur nom
// de fichier). On prend le nom courant tel quel — l'updater écrasera ce
// fichier sans le renommer, donc le nom historique perdure sur ces machines.
var processModule = SysProcess.GetCurrentProcess().MainModule var processModule = SysProcess.GetCurrentProcess().MainModule
?? throw new InvalidOperationException("Cannot locate current process module"); ?? throw new InvalidOperationException("Cannot locate current process module");
var targetExe = processModule.FileName!; var targetExe = processModule.FileName!;
@@ -64,20 +68,30 @@ public sealed class LauncherSelfUpdater : ILauncherSelfUpdater
var downloadedPath = await _downloadManager.DownloadAsync(downloadJob, progress, ct).ConfigureAwait(false); var downloadedPath = await _downloadManager.DownloadAsync(downloadJob, progress, ct).ConfigureAwait(false);
_logger.LogInformation("New launcher downloaded to {Path}", downloadedPath); _logger.LogInformation("New launcher downloaded to {Path}", downloadedPath);
// 3. Localise PSLauncher.Updater.exe (à côté du target) // 3. Localise l'updater à côté du target. Cherche d'abord le nouveau nom
var updaterPath = Path.Combine(installDir, "PSLauncher.Updater.exe"); // (PS_Launcher.Updater.exe, depuis v0.14.0) puis fallback sur l'ancien
// (PSLauncher.Updater.exe) pour compat backward avec les installs faites
// avec un installer < v0.14.0.
var updaterPath = Path.Combine(installDir, "PS_Launcher.Updater.exe");
if (!File.Exists(updaterPath)) if (!File.Exists(updaterPath))
{ {
// Fallback : tente de copier l'updater depuis le dossier d'install vers un staging var legacyUpdater = Path.Combine(installDir, "PSLauncher.Updater.exe");
// si jamais il a été supprimé. Pour la v1, on demande à l'utilisateur de réinstaller. if (File.Exists(legacyUpdater))
throw new FileNotFoundException( {
"PSLauncher.Updater.exe est manquant à côté de PSLauncher.exe. " + _logger.LogInformation("Using legacy updater path {Path} (pre-v0.14 install layout)", legacyUpdater);
"Réinstalle le launcher depuis l'installeur officiel.", updaterPath = legacyUpdater;
updaterPath); }
else
{
throw new FileNotFoundException(
"Updater (PS_Launcher.Updater.exe / PSLauncher.Updater.exe) introuvable à côté du launcher. " +
"Réinstalle le launcher depuis l'installeur officiel.",
updaterPath);
}
} }
// 4. Copie le .new dans le staging dir si downloaded est ailleurs // 4. Copie le .new dans le staging dir si downloaded est ailleurs
var newPath = Path.Combine(stagingDir, $"PSLauncher-{launcher.Version}.exe"); var newPath = Path.Combine(stagingDir, $"PS_Launcher-{launcher.Version}.exe");
if (!string.Equals(downloadedPath, newPath, StringComparison.OrdinalIgnoreCase)) if (!string.Equals(downloadedPath, newPath, StringComparison.OrdinalIgnoreCase))
{ {
if (File.Exists(newPath)) File.Delete(newPath); if (File.Exists(newPath)) File.Delete(newPath);

View File

@@ -6,9 +6,12 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<AssemblyName>PSLauncher.Updater</AssemblyName> <!-- Renommé v0.14.0 : PSLauncher.Updater.exe → PS_Launcher.Updater.exe.
La compat backward est gérée côté LauncherSelfUpdater qui essaie d'abord
le nouveau nom puis fallback sur l'ancien. -->
<AssemblyName>PS_Launcher.Updater</AssemblyName>
<RootNamespace>PSLauncher.Updater</RootNamespace> <RootNamespace>PSLauncher.Updater</RootNamespace>
<Version>0.13.0</Version> <Version>0.14.0</Version>
<ApplicationIcon>..\PSLauncher.App\Resources\favicon.ico</ApplicationIcon> <ApplicationIcon>..\PSLauncher.App\Resources\favicon.ico</ApplicationIcon>
<Company>ASTERION VR</Company> <Company>ASTERION VR</Company>
<Copyright>© 2026 ASTERION VR — All rights reserved</Copyright> <Copyright>© 2026 ASTERION VR — All rights reserved</Copyright>