fix(installer): upgrade-safe voie 1 — preserve identite+config, tue Lea avant copie

Poste clinique (Emilie) = install existante + Lea vive + config reelle
(machine_id lea-4zbgwxty, vrai serveur). L'installeur regenerait config.txt +
machine_id a chaque install => l'upgrade ecrasait l'identite fleet et forcait
la resaisie du serveur/token (Gap 1), et ne fermait pas la Lea en cours =>
DLL python-embed verrouillees (Gap 2).

Voie 1 :
- FindExistingInstallDir + LoadExistingConfig : detecte l'install, pre-remplit
  le wizard avec la VRAIE conf et memorise le machine_id.
- CurStepChanged(ssInstall) : preserve le machine_id existant (pas de regen).
- PrepareToInstall : tue Lea via le PID du lock avant la copie (libere les DLL).

Valide sur .11 (upgrade silencieux sur etat Emilie simule) : machine_id +
serveur preserves, fausse Lea tuee, lock retire, 4 fixes presents, exit 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dom
2026-07-01 23:48:40 +02:00
parent 94fd93ad19
commit 86e31ada34

View File

@@ -182,6 +182,7 @@ var
TokenPage: TInputQueryWizardPage; TokenPage: TInputQueryWizardPage;
MachineIdValue: string; MachineIdValue: string;
ConfigFilePath: string; ConfigFilePath: string;
ExistingMachineId: string;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// Helper : ajoute des guillemets autour d'une chaine // Helper : ajoute des guillemets autour d'une chaine
@@ -267,6 +268,72 @@ end;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
procedure LoadConfigFromCommandLine(); forward; procedure LoadConfigFromCommandLine(); forward;
// --------------------------------------------------------------------
// UPGRADE — trouve le dossier d'une install Lea existante (config.txt present)
// --------------------------------------------------------------------
function FindExistingInstallDir(): string;
var
Candidates: array[0..1] of string;
I: Integer;
begin
Result := '';
Candidates[0] := ExpandConstant('{localappdata}\Programs\Lea');
Candidates[1] := ExpandConstant('{autopf}\Lea');
for I := 0 to 1 do
begin
if FileExists(Candidates[I] + '\config.txt') then
begin
Result := Candidates[I];
Exit;
end;
end;
end;
// --------------------------------------------------------------------
// UPGRADE — lit le config.txt existant : pre-remplit le wizard avec la
// VRAIE conf du poste (serveur/token/user) et MEMORISE le machine_id pour
// le PRESERVER (ne pas regenerer une nouvelle identite fleet).
// --------------------------------------------------------------------
procedure LoadExistingConfig();
var
Dir, ConfPath: string;
Lines: TArrayOfString;
I, EqPos: Integer;
Line, Key, Value: string;
begin
ExistingMachineId := '';
Dir := FindExistingInstallDir();
if Dir = '' then Exit; // install neuve -> comportement par defaut
ConfPath := Dir + '\config.txt';
if LoadStringsFromFile(ConfPath, Lines) then
begin
for I := 0 to GetArrayLength(Lines) - 1 do
begin
Line := Trim(Lines[I]);
if (Length(Line) = 0) or (Line[1] = '#') then Continue;
EqPos := Pos('=', Line);
if EqPos = 0 then Continue;
Key := Trim(Copy(Line, 1, EqPos - 1));
Value := Trim(Copy(Line, EqPos + 1, Length(Line)));
if Key = 'RPA_SERVER_URL' then TokenPage.Values[0] := Value
else if Key = 'RPA_API_TOKEN' then TokenPage.Values[1] := Value
else if Key = 'RPA_USER_NAME' then EnrollmentPage.Values[0] := Value
else if Key = 'RPA_USER_EMAIL' then EnrollmentPage.Values[1] := Value
else if Key = 'RPA_USER_ID' then EnrollmentPage.Values[2] := Value
else if Key = 'RPA_MACHINE_ID' then ExistingMachineId := Value;
end;
end;
// Fallback : machine_id.txt si absent du config.txt
if (ExistingMachineId = '') and FileExists(Dir + '\machine_id.txt') then
begin
if LoadStringsFromFile(Dir + '\machine_id.txt', Lines) and (GetArrayLength(Lines) > 0) then
ExistingMachineId := Trim(Lines[0]);
end;
end;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// Initialisation : cree les pages custom d'enrollment // Initialisation : cree les pages custom d'enrollment
// -------------------------------------------------------------------- // --------------------------------------------------------------------
@@ -301,7 +368,11 @@ begin
TokenPage.Values[0] := SERVER_URL_DEFAULT; TokenPage.Values[0] := SERVER_URL_DEFAULT;
TokenPage.Values[1] := DEFAULT_TOKEN; TokenPage.Values[1] := DEFAULT_TOKEN;
// Si un fichier /CONFIG= est passe en ligne de commande, pre-remplir // UPGRADE : si une install existe, pre-remplir avec SA config (pas les
// defauts) et memoriser son machine_id pour le preserver.
LoadExistingConfig();
// Si un fichier /CONFIG= est passe en ligne de commande, pre-remplir (prioritaire)
LoadConfigFromCommandLine(); LoadConfigFromCommandLine();
end; end;
@@ -508,6 +579,29 @@ begin
DeleteFile(PsFile); DeleteFile(PsFile);
end; end;
// --------------------------------------------------------------------
// UPGRADE — AVANT la copie des fichiers : tuer une Lea en cours (via le
// PID du lock) pour liberer les DLL de python-embed. Evite une install
// partielle / "reboot required". Ne tue QUE le PID du lock (jamais tous
// les pythonw du poste).
// --------------------------------------------------------------------
function PrepareToInstall(var NeedsRestart: Boolean): String;
var
LockPath: string;
Lines: TArrayOfString;
ResultCode: Integer;
begin
Result := '';
LockPath := ExpandConstant('{app}\lea_agent.lock');
if FileExists(LockPath) then
begin
if LoadStringsFromFile(LockPath, Lines) and (GetArrayLength(Lines) > 0) then
Exec('taskkill.exe', '/F /PID ' + Trim(Lines[0]), '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
DeleteFile(LockPath);
Sleep(1500);
end;
end;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
// Hook : actions apres copie des fichiers (ssPostInstall) // Hook : actions apres copie des fichiers (ssPostInstall)
// -------------------------------------------------------------------- // --------------------------------------------------------------------
@@ -515,7 +609,10 @@ procedure CurStepChanged(CurStep: TSetupStep);
begin begin
if CurStep = ssInstall then if CurStep = ssInstall then
begin begin
// Genere le machine_id AVANT la copie des fichiers // UPGRADE : preserver l'identite existante ; sinon en generer une neuve.
if ExistingMachineId <> '' then
MachineIdValue := ExistingMachineId
else
MachineIdValue := GenerateMachineId(); MachineIdValue := GenerateMachineId();
end; end;