Files
Windows/powershell/libres-softwares-install.ps1
T

470 lines
18 KiB
PowerShell

# 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 = @"
<?xml version="1.0" encoding="UTF-8"?>
<DefaultAssociations>
<Association Identifier=".htm" ProgId="$($ProgIds.Htm)" ApplicationName="Firefox" />
<Association Identifier=".html" ProgId="$($ProgIds.Html)" ApplicationName="Firefox" />
<Association Identifier="http" ProgId="$($ProgIds.Http)" ApplicationName="Firefox" />
<Association Identifier="https" ProgId="$($ProgIds.Https)" ApplicationName="Firefox" />
</DefaultAssociations>
"@
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, "--source", "winget", "--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")