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:
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user