diff --git a/powershell/libres-softwares-install.ps1 b/powershell/libres-softwares-install.ps1 index f5bfda5..d81ce56 100644 --- a/powershell/libres-softwares-install.ps1 +++ b/powershell/libres-softwares-install.ps1 @@ -1,15 +1,262 @@ # Script d'installation de logiciels avec winget # Permet de choisir les logiciels a installer +[CmdletBinding(SupportsShouldProcess = $true)] +param() + +$ErrorActionPreference = "Continue" + . (Join-Path $PSScriptRoot "Initialize-Winget.ps1") Initialize-Winget +$IsAdministrator = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole( + [Security.Principal.WindowsBuiltInRole]::Administrator +) + +# --- Firefox installation functions --- + +function Install-FirefoxEsr { + param( + [string]$PackageId + ) + + Initialize-Winget + + Write-Host "Installing Firefox ESR with winget: $PackageId" -ForegroundColor Cyan + + if ($PSCmdlet.ShouldProcess($PackageId, "Install Firefox ESR")) { + $Arguments = @( + "install", + "--id", $PackageId, + "--silent", + "--accept-source-agreements", + "--accept-package-agreements" + ) + + $Process = Start-Process -FilePath "winget" -ArgumentList $Arguments -NoNewWindow -Wait -PassThru + + if ($Process.ExitCode -ne 0) { + throw "Firefox ESR installation failed. winget exit code: $($Process.ExitCode)" + } + + Write-Host "Firefox ESR installed or already present." -ForegroundColor Green + } +} + +function Get-FirefoxExecutablePath { + $FirefoxPaths = Get-FirefoxExecutablePaths + + if ($FirefoxPaths.Count -gt 0) { + return $FirefoxPaths[0] + } + + return $null +} + +function Get-FirefoxExecutablePaths { + $CandidatePaths = @() + + $AppPath = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe" -ErrorAction SilentlyContinue + if ($AppPath -and $AppPath.'(default)') { + $CandidatePaths += $AppPath.'(default)' + } + + $UninstallRoots = @( + "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*", + "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" + ) + + foreach ($Root in $UninstallRoots) { + $FirefoxInstall = Get-ItemProperty -Path $Root -ErrorAction SilentlyContinue | + Where-Object { $_.DisplayName -like "Mozilla Firefox*" -and $_.InstallLocation } | + Select-Object -First 1 + + if ($FirefoxInstall) { + $CandidatePaths += (Join-Path $FirefoxInstall.InstallLocation "firefox.exe") + } + } + + $CandidatePaths += @( + "$env:ProgramFiles\Mozilla Firefox\firefox.exe", + "$env:ProgramFiles\Mozilla Firefox ESR\firefox.exe", + "${env:ProgramFiles(x86)}\Mozilla Firefox\firefox.exe" + "${env:ProgramFiles(x86)}\Mozilla Firefox ESR\firefox.exe" + ) + + $FirefoxPaths = @() + + foreach ($Path in ($CandidatePaths | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -Unique)) { + if (Test-Path $Path) { + $FirefoxPaths += (Resolve-Path $Path).Path + } + } + + return @($FirefoxPaths | Select-Object -Unique) +} + +function Get-FirefoxAssociationProgIds { + $CapabilitiesPath = "HKLM:\SOFTWARE\Clients\StartMenuInternet\FIREFOX.EXE\Capabilities" + $UrlAssociationsPath = Join-Path $CapabilitiesPath "URLAssociations" + $FileAssociationsPath = Join-Path $CapabilitiesPath "FileAssociations" + + $UrlAssociations = Get-ItemProperty -Path $UrlAssociationsPath -ErrorAction SilentlyContinue + $FileAssociations = Get-ItemProperty -Path $FileAssociationsPath -ErrorAction SilentlyContinue + + $HttpProgId = $UrlAssociations.http + $HttpsProgId = $UrlAssociations.https + $HtmlProgId = $FileAssociations.".html" + $HtmProgId = $FileAssociations.".htm" + + if (-not $HttpProgId) { + $HttpProgId = "FirefoxURL-308046B0AF4A39CB" + } + + if (-not $HttpsProgId) { + $HttpsProgId = $HttpProgId + } + + if (-not $HtmlProgId) { + $HtmlProgId = "FirefoxHTML-308046B0AF4A39CB" + } + + if (-not $HtmProgId) { + $HtmProgId = $HtmlProgId + } + + return [PSCustomObject]@{ + Http = $HttpProgId + Https = $HttpsProgId + Html = $HtmlProgId + Htm = $HtmProgId + } +} + +function Get-FirefoxEnterprisePolicies { + $Policies = [ordered]@{ + policies = [ordered]@{ + DontCheckDefaultBrowser = $true + DisableDefaultBrowserAgent = $true + FirefoxHome = [ordered]@{ + Search = $true + TopSites = $false + SponsoredTopSites = $false + Pocket = $false + SponsoredPocket = $false + } + ExtensionSettings = [ordered]@{ + "uBlock0@raymondhill.net" = [ordered]@{ + installation_mode = "force_installed" + install_url = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi" + } + } + "3rdparty" = [ordered]@{ + Extensions = [ordered]@{ + "uBlock0@raymondhill.net" = [ordered]@{ + adminSettings = [ordered]@{ + selectedFilterLists = @( + "user-filters", + "ublock-filters", + "ublock-badware", + "ublock-privacy", + "ublock-abuse", + "ublock-unbreak", + "ublock-quick-fixes", + "easylist", + "easyprivacy", + "urlhaus-1", + "plowe-0" + ) + userSettings = [ordered]@{ + advancedUserEnabled = $false + cloudStorageEnabled = $false + contextMenuEnabled = $true + showIconBadge = $true + } + } + } + } + } + } + } + + return $Policies +} + +function Set-FirefoxEnterprisePolicies { + param( + [string[]]$FirefoxExecutables + ) + + $Policies = Get-FirefoxEnterprisePolicies + $PoliciesJson = $Policies | ConvertTo-Json -Depth 12 + $Utf8NoBom = [System.Text.UTF8Encoding]::new($false) + + foreach ($FirefoxExe in ($FirefoxExecutables | Select-Object -Unique)) { + $FirefoxDirectory = Split-Path -Parent $FirefoxExe + $DistributionDirectory = Join-Path $FirefoxDirectory "distribution" + $PoliciesPath = Join-Path $DistributionDirectory "policies.json" + + if ($PSCmdlet.ShouldProcess($PoliciesPath, "Write Firefox enterprise policies")) { + New-Item -Path $DistributionDirectory -ItemType Directory -Force | Out-Null + [System.IO.File]::WriteAllText($PoliciesPath, $PoliciesJson, $Utf8NoBom) + Get-Content -Path $PoliciesPath -Raw | ConvertFrom-Json | Out-Null + Write-Host "Firefox enterprise policies written: $PoliciesPath" -ForegroundColor Green + } + } +} + +function Set-FirefoxDefaultAssociations { + param( + [string]$OutputPath + ) + + $ProgIds = Get-FirefoxAssociationProgIds + $OutputDirectory = Split-Path -Parent $OutputPath + + $Xml = @" + + + + + + + +"@ + + if ($PSCmdlet.ShouldProcess($OutputPath, "Write Firefox default app associations")) { + New-Item -Path $OutputDirectory -ItemType Directory -Force | Out-Null + Set-Content -Path $OutputPath -Value $Xml -Encoding UTF8 + Write-Host "Default app associations written: $OutputPath" -ForegroundColor Green + } + + $SystemPolicyPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" + + if ($PSCmdlet.ShouldProcess($SystemPolicyPath, "Set default associations policy")) { + New-Item -Path $SystemPolicyPath -Force | Out-Null + New-ItemProperty -Path $SystemPolicyPath -Name "DefaultAssociationsConfiguration" -Value $OutputPath -PropertyType String -Force | Out-Null + Write-Host "Default associations policy configured." -ForegroundColor Green + } + + if ($PSCmdlet.ShouldProcess("DISM", "Import default app associations for new users")) { + $Arguments = "/Online", "/Import-DefaultAppAssociations:$OutputPath" + $Process = Start-Process -FilePath "dism.exe" -ArgumentList $Arguments -NoNewWindow -Wait -PassThru + + if ($Process.ExitCode -ne 0) { + Write-Warning "DISM failed to import default app associations. Exit code: $($Process.ExitCode)" + } + else { + Write-Host "Default app associations imported for future users." -ForegroundColor Green + } + } +} + +# --- Menu interactif --- + Write-Host "===========================================================" -ForegroundColor Cyan Write-Host " Script d'installation de logiciels avec winget" -ForegroundColor Cyan Write-Host "===========================================================" -ForegroundColor Cyan Write-Host "" -# Liste des logiciels disponibles avec leurs ID winget $logiciels = @( @{Nom = "Firefox ESR (FR)"; ID = "Mozilla.Firefox.ESR.fr"; Description = "Navigateur web Mozilla Firefox ESR"}, @{Nom = "7-Zip"; ID = "7zip.7zip"; Description = "Gestionnaire d'archives"}, @@ -23,7 +270,6 @@ $logiciels = @( @{Nom = "Thunderbird"; ID = "Mozilla.Thunderbird"; Description = "Client de messagerie"} ) -# Affichage de la liste des logiciels Write-Host "Logiciels disponibles a l'installation :" -ForegroundColor Green Write-Host "" for ($i = 0; $i -lt $logiciels.Count; $i++) { @@ -34,13 +280,11 @@ Write-Host "" Write-Host "===========================================================" -ForegroundColor Cyan Write-Host "" -# Selection des logiciels Write-Host "Entrez les numeros des logiciels a installer (separes par des virgules)" -ForegroundColor Yellow Write-Host "Exemple: 1,3,5 ou tapez 'tous' pour tout installer" -ForegroundColor Yellow Write-Host "" $choix = Read-Host "Votre choix" -# Traitement du choix $logicielsAInstaller = @() if ($choix.ToLower() -eq "tous" -or $choix.ToLower() -eq "all") { @@ -48,7 +292,7 @@ if ($choix.ToLower() -eq "tous" -or $choix.ToLower() -eq "all") { Write-Host "`nTous les logiciels seront installes." -ForegroundColor Green } else { $numeros = $choix -split ',' | ForEach-Object { $_.Trim() } - + foreach ($num in $numeros) { if ($num -match '^\d+$') { $index = [int]$num - 1 @@ -66,7 +310,6 @@ if ($logicielsAInstaller.Count -eq 0) { exit 0 } -# Confirmation Write-Host "`n===========================================================" -ForegroundColor Cyan Write-Host "Logiciels selectionnes pour l'installation :" -ForegroundColor Green foreach ($log in $logicielsAInstaller) { @@ -81,7 +324,6 @@ if ($confirmation -notmatch '^[oOyY]') { exit 0 } -# Installation des logiciels Write-Host "`n===========================================================" -ForegroundColor Cyan Write-Host "Debut de l'installation..." -ForegroundColor Green Write-Host "===========================================================" -ForegroundColor Cyan @@ -94,29 +336,44 @@ $resultats = @() foreach ($logiciel in $logicielsAInstaller) { Write-Host "`nInstallation de $($logiciel.Nom)..." -ForegroundColor Cyan Write-Host "ID winget: $($logiciel.ID)" -ForegroundColor Gray - + try { if ($logiciel.ID -eq "Mozilla.Firefox.ESR.fr") { - $installationFirefox = Join-Path $PSScriptRoot "Install-Firefox.ps1" - - if (-not (Test-Path $installationFirefox)) { - throw "Script d'installation Firefox introuvable: $installationFirefox" + if (-not $IsAdministrator) { + throw "Administrator rights are required to install and configure Firefox." } - $process = Start-Process -FilePath "powershell" -ArgumentList "-ExecutionPolicy", "Bypass", "-File", $installationFirefox -NoNewWindow -Wait -PassThru - } else { - # Installation avec winget - $process = Start-Process -FilePath "winget" -ArgumentList "install", "--id", $logiciel.ID, "--silent", "--accept-source-agreements", "--accept-package-agreements" -NoNewWindow -Wait -PassThru - } + $FirefoxAssociationsPath = "$env:ProgramData\WindowsLibreSoftwareToolkit\FirefoxDefaultAssociations.xml" + + Install-FirefoxEsr -PackageId $logiciel.ID + + $FirefoxExe = Get-FirefoxExecutablePath + $FirefoxExecutables = Get-FirefoxExecutablePaths + + if (-not $FirefoxExe -or $FirefoxExecutables.Count -eq 0) { + throw "Firefox was not found after installation. Check the winget package result and retry." + } + + Write-Host "Firefox found: $FirefoxExe" -ForegroundColor Cyan + Set-FirefoxEnterprisePolicies -FirefoxExecutables $FirefoxExecutables + Set-FirefoxDefaultAssociations -OutputPath $FirefoxAssociationsPath + Write-Host "Firefox ESR installed and configured. Restart Windows or sign out before creating/testing new users." -ForegroundColor Green - if ($process.ExitCode -eq 0) { Write-Host "OK $($logiciel.Nom) installe avec succes" -ForegroundColor Green $reussites++ $resultats += @{Logiciel = $logiciel.Nom; Statut = "Succes"} } else { - Write-Host "ERREUR Echec de l'installation de $($logiciel.Nom) (Code: $($process.ExitCode))" -ForegroundColor Red - $echecs++ - $resultats += @{Logiciel = $logiciel.Nom; Statut = "Echec"} + $process = Start-Process -FilePath "winget" -ArgumentList "install", "--id", $logiciel.ID, "--silent", "--accept-source-agreements", "--accept-package-agreements" -NoNewWindow -Wait -PassThru + + if ($process.ExitCode -eq 0) { + Write-Host "OK $($logiciel.Nom) installe avec succes" -ForegroundColor Green + $reussites++ + $resultats += @{Logiciel = $logiciel.Nom; Statut = "Succes"} + } else { + Write-Host "ERREUR Echec de l'installation de $($logiciel.Nom) (Code: $($process.ExitCode))" -ForegroundColor Red + $echecs++ + $resultats += @{Logiciel = $logiciel.Nom; Statut = "Echec"} + } } } catch { Write-Host "ERREUR lors de l'installation de $($logiciel.Nom): $_" -ForegroundColor Red @@ -125,7 +382,6 @@ foreach ($logiciel in $logicielsAInstaller) { } } -# Resume de l'installation Write-Host "`n===========================================================" -ForegroundColor Cyan Write-Host "Resume de l'installation" -ForegroundColor Cyan Write-Host "===========================================================" -ForegroundColor Cyan