# ========================================================================= # INSTALL-APPS.PS1 - Installation des applications via Winget # Exécution en contexte SYSTEM lors du déploiement MDT # ========================================================================= # ========================================================================= # 0. CONFIGURATION DU CONTEXTE ET VARIABLES DYNAMIQUES # ========================================================================= $SystemRoot = $env:SystemRoot # C:\Windows $SystemDrive = $env:SystemDrive # C: $CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name $IsSystem = $CurrentUser -like "*SYSTEM" -or $CurrentUser -like "*S-1-5-18" Write-Host "========================================================" -ForegroundColor Cyan Write-Host " CONFIGURATION CONTEXTE MDT" Write-Host "========================================================" -ForegroundColor Cyan Write-Host "Utilisateur: $CurrentUser (SYSTEM: $IsSystem)" Write-Host "SystemRoot: $SystemRoot" Write-Host "SystemDrive: $SystemDrive" # ========================================================================= # 1. CONFIGURATION DU FICHIER LOG WINDOWS (Chemin dynamique) # ========================================================================= $LogDirectory = Join-Path $SystemRoot "Logs\MDT_Apps" if (!(Test-Path $LogDirectory)) { $null = New-Item -ItemType Directory -Force -Path $LogDirectory -ErrorAction SilentlyContinue } $DateStamp = Get-Date -Format "yyyyMMdd_HHmmss" $LogPath = Join-Path $LogDirectory "Installation_Applications_$DateStamp.log" Write-Host "Répertoire logs: $LogDirectory" # Début de l'enregistrement Start-Transcript -Path $LogPath -Append -Force Write-Host "========================================================" Write-Host " DEBUT DU SCRIPT D'INSTALLATION DES APPLICATIONS" Write-Host " Fichier log : $LogPath" Write-Host "========================================================" # ========================================================================= # 2. CONFIGURATION DE L'ENVIRONNEMENT SYSTEM POUR WINGET # ========================================================================= $WingetDataPath = Join-Path $SystemRoot "System32\config\systemprofile\AppData\Local\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState" if (!(Test-Path $WingetDataPath)) { $null = New-Item -ItemType Directory -Force -Path $WingetDataPath -ErrorAction SilentlyContinue } $SettingsFile = Join-Path $WingetDataPath "settings.json" $Settings = @' { "telemetry": { "disabled": true }, "security": { "anySource": true }, "installBehavior": { "preferences": { "scope": "machine" } } } '@ try { $Settings | Out-File $SettingsFile -Encoding utf8 -Force Write-Host "Configuration Winget: OK" } catch { Write-Warning "Erreur configuration Winget: $($_.Exception.Message)" } # ========================================================================= # 3. VERIFICATION / UPGRADE WINGET V7 # ========================================================================= Write-Host "" Write-Host "========================================================" Write-Host " VERIFICATION WINGET V7" Write-Host "========================================================" try { $WingetVersion = & winget --version 2>$null Write-Host "Version actuelle: $WingetVersion" # Upgrade si nécessaire Write-Host "Tentative de mise à jour Winget..." & winget upgrade winget --accept-source-agreements --silent 2>$null | Out-Null Start-Sleep -Seconds 2 $NewVersion = & winget --version 2>$null Write-Host "Version après upgrade: $NewVersion" } catch { Write-Warning "Erreur lors de la gestion Winget: $($_.Exception.Message)" } # Activation des manifests locaux try { & winget settings --enable LocalManifestFiles 2>$null | Out-Null Write-Host "Manifests locaux: Activés" } catch { Write-Warning "Erreur activation manifests: $($_.Exception.Message)" } # ========================================================================= # 4. RECHERCHE ET TRAITEMENT DES APPLICATIONS # ========================================================================= Write-Host "" Write-Host "========================================================" Write-Host " RECHERCHE DES MANIFESTS D'APPLICATION" Write-Host "========================================================" $AppsFolder = Join-Path $PSScriptRoot "Apps" Write-Host "Dossier des applications: $AppsFolder" if (!(Test-Path $AppsFolder)) { Write-Error "Dossier Applications introuvable: $AppsFolder" Stop-Transcript exit 1 } $Manifests = Get-ChildItem -Path $AppsFolder -Filter "*.yaml" -ErrorAction SilentlyContinue $TotalApps = $Manifests.Count Write-Host "Manifests trouvés: $TotalApps" if ($TotalApps -eq 0) { Write-Warning "Aucun fichier manifest .yaml trouvé dans $AppsFolder" Stop-Transcript exit 1 } # ========================================================================= # 5. FONCTION DE VERIFICATION D'INSTALLATION # ========================================================================= function Test-IsAppInstalled { [CmdletBinding()] param([string]$AppName) try { $Paths = @( "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*", "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" ) $Result = Get-ItemProperty $Paths -ErrorAction SilentlyContinue | ` Where-Object { $_.DisplayName -and $_.DisplayName -like "*$AppName*" } return ($null -ne $Result) } catch { Write-Warning "Erreur lors de la vérification $AppName : $($_.Exception.Message)" return $false } } # ========================================================================= # 6. PIPELINE DE TRAITEMENT DES APPLICATIONS # ========================================================================= Write-Host "" Write-Host "========================================================" Write-Host " INSTALLATION DES APPLICATIONS" Write-Host "========================================================" $Global:CurrentAppIndex = 0 $Manifests | ForEach-Object { $Global:CurrentAppIndex++ $Manifest = $_ $CleanName = ($Manifest.BaseName -split "_")[0] $Sanitized = $CleanName -replace '[^a-zA-Z0-9]', '' Write-Host "[$Global:CurrentAppIndex/$TotalApps] Vérification : $CleanName" -ForegroundColor Cyan if (Test-IsAppInstalled -AppName $CleanName) { Write-Host " -> PASSER : Déjà installé." -ForegroundColor Yellow return } $InstallerFile = Get-ChildItem -Path $AppsFolder | Where-Object { $_.Extension -in ".exe", ".msi" -and ` ($_.Name -ilike "*$Sanitized*" -or $_.Name -ilike "*$CleanName*") } | Select-Object -First 1 if (!$InstallerFile) { Write-Host " -> ÉCHEC : Fichier installateur introuvable pour $CleanName" -ForegroundColor Red return } $FullFileName = $InstallerFile.Name.ToLower() $Executable = $InstallerFile.FullName $Arguments = "/S" # ========================================================================= # Détermination des arguments selon le type de fichier # ========================================================================= if ($InstallerFile.Extension -eq ".msi") { $Executable = "msiexec.exe" $Arguments = "/i `"$($InstallerFile.FullName)`" /qn /norestart" if (Get-Process -Name "msiexec" -ErrorAction SilentlyContinue) { Write-Host " -> Nettoyage processus msiexec..." -ForegroundColor DarkYellow Stop-Process -Name "msiexec" -Force -ErrorAction SilentlyContinue Start-Sleep -Seconds 2 } } else { switch -regex ($FullFileName) { "7z|7zip" { $Arguments = "/S" } "notepad" { $Arguments = "/S" } "vlc" { $Arguments = "/S" } "audacity" { $Arguments = "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART" } "python" { $Arguments = "/quiet InstallAllUsers=1 PrependPath=1 Include_test=0" } default { $Arguments = "/S" } } } # ========================================================================= # Exécution de l'installation # ========================================================================= try { Write-Host " -> Installation: $($InstallerFile.Name)" -ForegroundColor White Write-Host " Exécutable: $Executable" Write-Host " Arguments: $Arguments" $Process = Start-Process -FilePath $Executable -ArgumentList $Arguments ` -NoNewWindow -Wait -PassThru -ErrorAction Stop $ExitCode = $Process.ExitCode if ($ExitCode -eq 0 -or $ExitCode -eq 3010) { Write-Host " -> SUCCÈS (Code: $ExitCode)`n" -ForegroundColor Green } else { Write-Host " -> ÉCHEC. Code erreur: $ExitCode" -ForegroundColor Red Write-Host " Args: $Arguments`n" -ForegroundColor DarkRed } } catch { Write-Host " -> ERREUR CRITIQUE: $($_.Exception.Message)`n" -ForegroundColor Red } } # ========================================================================= # 7. FINALISATION # ========================================================================= Write-Host "========================================================" Write-Host " TRAITEMENT TERMINÉ" Write-Host "========================================================" Write-Host "Logs disponibles: $LogPath" Stop-Transcript