# Script d'installation de logiciels avec winget # Permet de choisir les logiciels a installer [CmdletBinding(SupportsShouldProcess = $true)] param() $ErrorActionPreference = "Continue" function Initialize-Winget { if (Get-Command winget -ErrorAction SilentlyContinue) { return } Write-Host "winget not found in PATH. Attempting repair..." -ForegroundColor Yellow $MachinePath = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") $UserPath = [System.Environment]::GetEnvironmentVariable("PATH", "User") $env:PATH = $MachinePath + ";" + $UserPath if (Get-Command winget -ErrorAction SilentlyContinue) { Write-Host "winget available after PATH refresh." -ForegroundColor Green return } $AppInstaller = Get-AppxPackage -Name "Microsoft.DesktopAppInstaller" -ErrorAction SilentlyContinue if (-not $AppInstaller) { $AppInstaller = Get-AppxPackage -AllUsers -Name "Microsoft.DesktopAppInstaller" -ErrorAction SilentlyContinue } if ($AppInstaller) { Write-Host "Re-registering App Installer..." -ForegroundColor Yellow try { $Manifest = Join-Path $AppInstaller.InstallLocation "AppxManifest.xml" Add-AppxPackage -DisableDevelopmentMode -Register $Manifest -ErrorAction Stop $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User") if (Get-Command winget -ErrorAction SilentlyContinue) { Write-Host "winget repaired." -ForegroundColor Green return } } catch { Write-Warning "Re-registration failed: $_" } } $StagedPackage = Get-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -eq "Microsoft.DesktopAppInstaller" } | Select-Object -First 1 if ($StagedPackage) { Write-Host "Installing App Installer from provisioned package..." -ForegroundColor Yellow try { Add-AppxPackage -Path $StagedPackage.PackagePath -ErrorAction Stop $env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User") if (Get-Command winget -ErrorAction SilentlyContinue) { Write-Host "winget installed." -ForegroundColor Green return } } catch { Write-Warning "Installation from provisioned package failed: $_" } } Write-Error ("winget is not available and could not be repaired automatically.`n" + "Install App Installer from the Microsoft Store: " + "ms-windows-store://pdp/?productid=9nblggh4nns1") exit 1 } 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, "--source", "winget", "--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 "" $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"}, @{Nom = "VLC Media Player"; ID = "VideoLAN.VLC"; Description = "Lecteur multimedia"}, @{Nom = "OnlyOffice"; ID = "ONLYOFFICE.DesktopEditors"; Description = "Suite bureautique"}, @{Nom = "LibreOffice"; ID = "TheDocumentFoundation.LibreOffice"; Description = "Suite bureautique libre"}, @{Nom = "GIMP"; ID = "GIMP.GIMP.3"; Description = "Editeur d'images"}, @{Nom = "Inkscape"; ID = "Inkscape.Inkscape"; Description = "Editeur de graphiques vectoriels"}, @{Nom = "Chromium"; ID = "Hibbiki.Chromium"; Description = "Navigateur web open source"}, @{Nom = "Bitwarden"; ID = "Bitwarden.Bitwarden"; Description = "Gestionnaire de mots de passe"}, @{Nom = "Thunderbird"; ID = "Mozilla.Thunderbird"; Description = "Client de messagerie"} ) Write-Host "Logiciels disponibles a l'installation :" -ForegroundColor Green Write-Host "" for ($i = 0; $i -lt $logiciels.Count; $i++) { Write-Host ("{0,2}. [{1}] {2}" -f ($i + 1), " ", $logiciels[$i].Nom) -ForegroundColor White Write-Host (" {0}" -f $logiciels[$i].Description) -ForegroundColor Gray } Write-Host "" Write-Host "===========================================================" -ForegroundColor Cyan Write-Host "" 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" $logicielsAInstaller = @() if ($choix.ToLower() -eq "tous" -or $choix.ToLower() -eq "all") { $logicielsAInstaller = $logiciels 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 if ($index -ge 0 -and $index -lt $logiciels.Count) { $logicielsAInstaller += $logiciels[$index] } else { Write-Host "Numero invalide ignore: $num" -ForegroundColor Red } } } } if ($logicielsAInstaller.Count -eq 0) { Write-Host "`nAucun logiciel selectionne. Fin du script." -ForegroundColor Yellow exit 0 } Write-Host "`n===========================================================" -ForegroundColor Cyan Write-Host "Logiciels selectionnes pour l'installation :" -ForegroundColor Green foreach ($log in $logicielsAInstaller) { Write-Host " - $($log.Nom)" -ForegroundColor White } Write-Host "===========================================================" -ForegroundColor Cyan Write-Host "" $confirmation = Read-Host "Confirmer l'installation ? (O/N)" if ($confirmation -notmatch '^[oOyY]') { Write-Host "`nInstallation annulee." -ForegroundColor Yellow exit 0 } Write-Host "`n===========================================================" -ForegroundColor Cyan Write-Host "Debut de l'installation..." -ForegroundColor Green Write-Host "===========================================================" -ForegroundColor Cyan Write-Host "" $reussites = 0 $echecs = 0 $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") { if (-not $IsAdministrator) { throw "Administrator rights are required to install and configure Firefox." } $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 Write-Host "OK $($logiciel.Nom) installe avec succes" -ForegroundColor Green $reussites++ $resultats += @{Logiciel = $logiciel.Nom; Statut = "Succes"} } else { $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 $echecs++ $resultats += @{Logiciel = $logiciel.Nom; Statut = "Erreur"} } } Write-Host "`n===========================================================" -ForegroundColor Cyan Write-Host "Resume de l'installation" -ForegroundColor Cyan Write-Host "===========================================================" -ForegroundColor Cyan Write-Host "" foreach ($resultat in $resultats) { if ($resultat.Statut -eq "Succes") { Write-Host "[OK] $($resultat.Logiciel): $($resultat.Statut)" -ForegroundColor Green } else { Write-Host "[X] $($resultat.Logiciel): $($resultat.Statut)" -ForegroundColor Red } } Write-Host "" Write-Host "Total: $reussites reussite(s), $echecs echec(s)" -ForegroundColor $(if ($echecs -eq 0) { "Green" } else { "Yellow" }) Write-Host "===========================================================" -ForegroundColor Cyan Write-Host "" Write-Host "Appuyez sur une touche pour quitter..." $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")