<# .SYNOPSIS Met a jour l'agent Lea (installe per-user) via un script d'OUVERTURE DE SESSION GPO. .DESCRIPTION ============================================================================ A DEPLOYER EN : User Configuration > Policies > Windows Settings > Scripts (Logon/Logoff) > Logon. ET PAS EN "Computer > Startup". ============================================================================ RAISON (non negociable) : l'installeur Lea est PER-USER (%LOCALAPPDATA%\Programs\Lea, cle de desinstallation sous HKCU). Un script de DEMARRAGE MACHINE tourne en contexte SYSTEM : il ne verrait NI l'installation NI HKCU du collaborateur -> il ne mettrait jamais rien a jour. Le contexte UTILISATEUR est donc obligatoire. Le script, a chaque ouverture de session : 1. Detecte la version installee (DisplayVersion de la cle de desinstallation Inno dans HKCU — primaire pour un install EXE ; fallback RPA_AGENT_VERSION du config.txt, present uniquement sur les installs via ZIP). 2. La compare a la version cible (comparaison semver correcte : 1.0.2 < 1.0.10, contrairement a une comparaison de chaines). 3. Si plus ancienne : lance l'installeur en mode SILENCIEUX + UPGRADE-SAFE (SANS /CONFIG -> machine_id, serveur et token du poste PRESERVES). 4. Journalise le resultat. IDEMPOTENT : ne refait rien si deja a jour. Ne leve JAMAIS d'exception bloquant l'ouverture de session (tout en try/catch, sortie 0 sur erreur non geree). .NOTES Execution : configurer la GPO pour lancer powershell.exe -NoProfile -ExecutionPolicy Bypass -File Deploy-LeaUpdate.ps1 Test sur un poste (lecture seule, ne telecharge/installe RIEN) : powershell.exe -NoProfile -ExecutionPolicy Bypass -File Deploy-LeaUpdate.ps1 -DryRun #> param( # -DryRun : teste la DECISION (version installee vs cible) et journalise ce # qui SERAIT fait, sans rien telecharger ni installer. Pour valider un poste. [switch]$DryRun, # Overrides optionnels (sinon = valeurs du bloc PARAMETRES ci-dessous). # Utiles pour tester un poste (cible bumpee, journal local) sans editer le script. [string]$TargetVersionOverride, [string]$LogShareOverride ) # ============================================================================ # PARAMETRES A ADAPTER PAR LE DSI / Julien (les 3 seules lignes a toucher) # ============================================================================ # Source de l'installeur : chemin UNC du domaine (recommande) OU URL http(s). # UNC : \\SRV-FICHIERS\Deploiement$\Lea\Lea-Setup-v1.0.2.exe # HTTPS : https://lea.labs.laurinebazin.design/api/fleet/installer/exe $ExeSource = '\\SRV-FICHIERS\Deploiement$\Lea\Lea-Setup-v1.0.2.exe' # Version cible : DOIT correspondre a l'EXE ci-dessus. $TargetVersion = '1.0.2' # Dossier de journalisation partage (audit Julien). Vide => journal local %TEMP%. $LogShare = '\\SRV-FICHIERS\Deploiement$\Lea\logs' # ============================================================================ # Ne rien modifier en dessous de cette ligne. # ============================================================================ # Overrides de ligne de commande (prioritaires sur le bloc PARAMETRES). if ($TargetVersionOverride) { $TargetVersion = $TargetVersionOverride } if ($PSBoundParameters.ContainsKey('LogShareOverride')) { $LogShare = $LogShareOverride } $InstallDir = Join-Path $env:LOCALAPPDATA 'Programs\Lea' $ConfigTxt = Join-Path $InstallDir 'config.txt' $AppUninst = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\{B3F9A1E2-5C4D-4E7F-9A1B-2C3D4E5F6789}_is1' function Write-Log([string]$msg) { $line = '{0} {1}\{2} {3}' -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $env:COMPUTERNAME, $env:USERNAME, $msg Write-Output $line # Journalisation best-effort : ne DOIT jamais perturber l'ouverture de session. # -ErrorAction SilentlyContinue car un partage injoignable produit une erreur # NON-terminante (non capturee par try/catch) — verifie sur poste reel .11. try { $dir = if ($LogShare) { $LogShare } else { Join-Path $env:TEMP 'Lea-update-logs' } if (-not (Test-Path $dir -ErrorAction SilentlyContinue)) { New-Item -ItemType Directory -Path $dir -Force -ErrorAction SilentlyContinue | Out-Null } $file = Join-Path $dir ('{0}_{1}.log' -f $env:COMPUTERNAME, $env:USERNAME) Add-Content -Path $file -Value $line -Encoding UTF8 -ErrorAction SilentlyContinue } catch { } } function Get-InstalledVersion { # 1. Source de verite pour un install EXE (Inno) : DisplayVersion dans HKCU # (install per-user). Toujours ecrite par l'installeur -> methode primaire. # Verifie sur poste reel .11 : le config.txt genere par l'EXE ne contient # PAS de ligne de version, seul le registre fait foi. if (Test-Path $AppUninst) { $dv = (Get-ItemProperty -Path $AppUninst -Name DisplayVersion -ErrorAction SilentlyContinue).DisplayVersion if ($dv) { return $dv } } # 2. Fallback : RPA_AGENT_VERSION dans config.txt (present sur les installs # via ZIP/Python ; absent des installs via EXE). if (Test-Path $ConfigTxt) { $m = Select-String -Path $ConfigTxt -Pattern '^\s*RPA_AGENT_VERSION\s*=\s*(.+?)\s*$' -ErrorAction SilentlyContinue if ($m) { return $m.Matches[0].Groups[1].Value.Trim() } } return $null } function ConvertTo-VersionParts([string]$v) { $clean = ($v -replace '^[vV]', '').Trim() $parts = New-Object System.Collections.Generic.List[int] foreach ($p in ($clean -split '\.')) { $n = 0 if ([int]::TryParse($p, [ref]$n)) { $parts.Add($n) } else { $parts.Add(0) } } while ($parts.Count -lt 3) { $parts.Add(0) } return $parts } function Compare-Semver([string]$a, [string]$b) { # -1 si ab. Tolerant (piege 1.0.2 < 1.0.10). $pa = ConvertTo-VersionParts $a $pb = ConvertTo-VersionParts $b $max = [Math]::Max($pa.Count, $pb.Count) for ($i = 0; $i -lt $max; $i++) { $va = if ($i -lt $pa.Count) { $pa[$i] } else { 0 } $vb = if ($i -lt $pb.Count) { $pb[$i] } else { 0 } if ($va -lt $vb) { return -1 } if ($va -gt $vb) { return 1 } } return 0 } try { $installed = Get-InstalledVersion if (-not $installed) { Write-Log 'Lea non installe sur ce profil -> ignore (les nouveaux postes passent par le dashboard).' exit 0 } if ((Compare-Semver $installed $TargetVersion) -ge 0) { Write-Log ('Deja a jour (installe={0}, cible={1}) -> rien a faire.' -f $installed, $TargetVersion) exit 0 } if ($DryRun) { Write-Log ('[DryRun] MAJ qui SERAIT appliquee : {0} -> {1}. Aucune action (ni telechargement ni installation).' -f $installed, $TargetVersion) exit 0 } Write-Log ('MAJ requise : installe={0} < cible={1}. Recuperation de l''installeur...' -f $installed, $TargetVersion) # Recuperer l'EXE (UNC ou URL) vers un fichier temporaire local. $localExe = Join-Path $env:TEMP ('Lea-Setup-{0}.exe' -f $TargetVersion) if ($ExeSource -match '^(?i)https?://') { Invoke-WebRequest -Uri $ExeSource -OutFile $localExe -UseBasicParsing } else { Copy-Item -Path $ExeSource -Destination $localExe -Force } if (-not (Test-Path $localExe)) { Write-Log ('ECHEC : installeur introuvable apres recuperation ({0}).' -f $ExeSource) exit 1 } # Installation SILENCIEUSE + UPGRADE-SAFE (sans /CONFIG : identite du poste preservee). # L'installeur arrete Lea (via lock), sauvegarde _backup, puis met a jour. $logInstall = Join-Path $env:TEMP ('Lea-upgrade-{0}.log' -f (Get-Date -Format 'yyyyMMdd_HHmmss')) $installArgs = @('/VERYSILENT', '/SUPPRESSMSGBOXES', '/NORESTART', ('/LOG={0}' -f $logInstall)) $proc = Start-Process -FilePath $localExe -ArgumentList $installArgs -Wait -PassThru $rc = $proc.ExitCode if ($rc -eq 0) { $now = Get-InstalledVersion Write-Log ('MAJ OK : {0} -> {1} (code 0).' -f $installed, $now) } else { Write-Log ('ECHEC MAJ : code {0}. Journal installeur : {1}.' -f $rc, $logInstall) } exit $rc } catch { Write-Log ('ERREUR non geree : ' + $_.Exception.Message) exit 0 # ne JAMAIS bloquer l'ouverture de session }