Ajout d'un fond d'écran personnalisé si fourni dans DeployCenter.ini

Renommage du profil unattend pour mieux correspondre à ce qu'il fait.
Ajout d'un warning si WinRE n'est pas assez grands au regard des préconisations Microsoft et du redémarrage automatique si l'installation réussi.
This commit is contained in:
benoit committed 2026-10-17 21:28:34 +02:00
1 parent e067721763
commit cb917c97ce
11 files changed
+161 -23

No files matched your search

+9
View File
@@ -14,6 +14,9 @@ function Read-DeployCenterConfig {
UnattendAdminDisplayName = 'Administrateur local'
UnattendAdminGroup = 'Administrators'
UnattendAdminPasswordBase64 = ''
UnattendSupportProvider = ''
UnattendSupportAppURL = ''
UnattendWallpaperPath = 'Assets\blorand.png'
}
if (-not (Test-Path -LiteralPath $ConfigPath -PathType Leaf)) { return $config }
@@ -46,6 +49,12 @@ function Read-DeployCenterConfig {
$config.UnattendAdminGroup = $value
} elseif ($section -ieq 'Unattend' -and $key -ieq 'AdminPasswordBase64') {
$config.UnattendAdminPasswordBase64 = $value
} elseif ($section -ieq 'Unattend' -and $key -ieq 'SupportProvider') {
$config.UnattendSupportProvider = $value
} elseif ($section -ieq 'Unattend' -and $key -ieq 'SupportAppURL') {
$config.UnattendSupportAppURL = $value
} elseif ($section -ieq 'Unattend' -and $key -ieq 'WallpaperPath') {
$config.UnattendWallpaperPath = $value
}
}
return $config
+44 -1
View File
@@ -444,6 +444,7 @@ function Invoke-DeployCenterWindowsDeployment {
if ($null -eq $UnattendConfiguration) { throw 'La configuration DeployCenter.ini est absente pour le profil Unattend sélectionné.' }
Test-DeployCenterUnattendConfiguration -Profile $UnattendProfile -Configuration $UnattendConfiguration -HostName ([string]$HostName)
}
$winreRecommendationWarnings = @()
if ([string]$Firmware -ne [string]$Profile.Firmware) {
throw ("Le profil {0} exige le firmware {1}, détecté : {2}." -f $Profile.Name, $Profile.Firmware, $Firmware)
}
@@ -464,6 +465,25 @@ function Invoke-DeployCenterWindowsDeployment {
}
if (-not $Edition.Index -or [int]$Edition.Index -lt 1) { throw "L’index de l’édition Windows est invalide." }
$wallpaperSourcePath = $null
if ($null -ne $UnattendProfile -and $null -ne $UnattendConfiguration) {
$configuredWallpaperPath = [string]$UnattendConfiguration.UnattendWallpaperPath
if (-not [string]::IsNullOrWhiteSpace($configuredWallpaperPath)) {
$deployRoot = Split-Path -Path $PSScriptRoot -Parent
if ([System.IO.Path]::IsPathRooted($configuredWallpaperPath)) {
$wallpaperSourcePath = [System.IO.Path]::GetFullPath($configuredWallpaperPath)
} else {
$wallpaperSourcePath = [System.IO.Path]::GetFullPath((Join-Path $deployRoot $configuredWallpaperPath))
}
if ([System.IO.Path]::GetExtension($wallpaperSourcePath) -notin @('.png', '.jpg', '.bmp')) {
throw 'WallpaperPath doit désigner un fichier .png, .jpg ou .bmp.'
}
if (-not (Test-Path -LiteralPath $wallpaperSourcePath -PathType Leaf)) {
throw "Image de fond introuvable : $wallpaperSourcePath"
}
}
}
$disk = Get-Disk -Number ([int]$DiskInfo.Index) -ErrorAction Stop
if ($disk.IsBoot -or $disk.IsSystem) { throw 'Le disque sélectionné héberge le système WinPE et ne peut pas être effacé.' }
if ($disk.IsOffline) { [void](Set-Disk -Number $disk.Number -IsOffline $false -ErrorAction Stop) }
@@ -577,11 +597,28 @@ function Invoke-DeployCenterWindowsDeployment {
throw "Le profil doit définir les rôles System, Windows et Recovery pour permettre l’installation UEFI avec WinRE."
}
$wallpaperTargetPath = $null
$wallpaperDestination = $null
if ($wallpaperSourcePath) {
$wallpaperName = [System.IO.Path]::GetFileName($wallpaperSourcePath)
$wallpaperDirectory = Join-Path $windowsRoot 'Web\Wallpaper\DeployCenter'
$wallpaperDestination = Join-Path $wallpaperDirectory $wallpaperName
$wallpaperTargetPath = '%WINDIR%\Web\Wallpaper\DeployCenter\' + $wallpaperName
if ($wallpaperDestination.Length -gt 259) { throw "Le chemin configuré du fond d’écran dépasse 259 caractères dans Windows." }
}
if ($ProgressAction) { & $ProgressAction "Application de Windows sur ${windowsLetter}:…" }
Invoke-DeployCenterNativeCommand -FilePath $dismPath -Arguments @(
'/Apply-Image', "/ImageFile:$deploymentImagePath", "/Index:$([int]$Edition.Index)", "/ApplyDir:$windowsPath", '/CheckIntegrity'
) -TemporaryRoot $TemporaryRoot -LogAction $LogAction -ProgressAction $ProgressAction
if ($wallpaperSourcePath) {
New-Item -Path $wallpaperDirectory -ItemType Directory -Force -ErrorAction Stop | Out-Null
Copy-Item -LiteralPath $wallpaperSourcePath -Destination $wallpaperDestination -Force -ErrorAction Stop
Write-DeployCenterDeploymentLog -LogAction $LogAction `
-Message ("Image de fond copiée dans Windows : {0}." -f $wallpaperDestination) -Level 'INFO'
}
if ($ProgressAction) { & $ProgressAction 'Vérification de la capacité de la partition WinRE…' }
$sourceWinre = Join-Path $windowsRoot 'System32\Recovery\winre.wim'
if (-not (Test-Path -LiteralPath $sourceWinre -PathType Leaf)) {
@@ -615,6 +652,7 @@ function Invoke-DeployCenterWindowsDeployment {
}
if ($recommendationWarnings.Count -gt 0) {
$warningDetails = $recommendationWarnings -join '; '
$winreRecommendationWarnings = @($recommendationWarnings.ToArray())
$message = "Avertissement WinRE : les recommandations Microsoft ne sont pas toutes respectées ($warningDetails). La copie de winre.wim reste possible ; le déploiement continue."
Write-DeployCenterDeploymentLog -LogAction $LogAction -Message $message -Level 'WARNING'
} else {
@@ -625,7 +663,8 @@ function Invoke-DeployCenterWindowsDeployment {
if ($ProgressAction) { & $ProgressAction 'Préparation du fichier de réponses Windows…' }
$editionArchitecture = if ($Edition.Edition -and $Edition.Edition.Architecture) { [string]$Edition.Edition.Architecture } else { [string]$Edition.Architecture }
$unattendXml = New-DeployCenterUnattendXml -Profile $UnattendProfile `
-Configuration $UnattendConfiguration -HostName ([string]$HostName) -Architecture $editionArchitecture
-Configuration $UnattendConfiguration -HostName ([string]$HostName) `
-Architecture $editionArchitecture -WallpaperPath ([string]$wallpaperTargetPath)
[System.IO.File]::WriteAllText($unattendPath, $unattendXml, (New-Object System.Text.UTF8Encoding($false)))
$pantherUnattendDirectory = Join-Path $windowsRoot 'Panther\Unattend'
New-Item -Path $pantherUnattendDirectory -ItemType Directory -Force -ErrorAction Stop | Out-Null
@@ -703,6 +742,10 @@ function Invoke-DeployCenterWindowsDeployment {
} finally {
Remove-DeployCenterDismSourceAccess -Lease $sourceLease -TemporaryRoot $TemporaryRoot -LogAction $LogAction
}
return [pscustomobject]@{
WinRERecommendationWarnings = @($winreRecommendationWarnings)
WinRERecommendationsMet = ($winreRecommendationWarnings.Count -eq 0)
}
}
Export-ModuleMember -Function Invoke-DeployCenterWindowsDeployment, Restart-DeployCenterWinPE
+4 -3
View File
@@ -138,7 +138,7 @@ function New-DeployCenterDeploymentControls {
$unattendLabel.Name = 'lblUnattendProfile'
$unattendLabel.Text = 'Configuration de première ouverture'
$unattendLabel.Location = New-Object System.Drawing.Point(12, 190)
$unattendLabel.Size = New-Object System.Drawing.Size(320, 18)
$unattendLabel.Size = New-Object System.Drawing.Size(320, 17)
$unattendLabel.Font = $Font
$unattendLabel.ForeColor = $Theme.Text
$unattendLabel.BackColor = [System.Drawing.Color]::Transparent
@@ -516,7 +516,8 @@ function Show-DeployCenterDeploymentComplete {
[Parameter(Mandatory=$true)][string]$Message,
[Parameter(Mandatory=$true)][System.Windows.Forms.Form]$Owner,
[Parameter(Mandatory=$true)][System.Collections.IDictionary]$Theme,
[Parameter(Mandatory=$true)][System.Drawing.Font]$Font
[Parameter(Mandatory=$true)][System.Drawing.Font]$Font,
[bool]$RestartByDefault = $true
)
$dialog = New-Object System.Windows.Forms.Form
@@ -562,7 +563,7 @@ function Show-DeployCenterDeploymentComplete {
$restartCheckBox.Text = 'Redémarrer cet ordinateur après fermeture'
$restartCheckBox.Location = New-Object System.Drawing.Point(64, ($messageHeight + 34))
$restartCheckBox.Size = New-Object System.Drawing.Size(380, 26)
$restartCheckBox.Checked = $true
$restartCheckBox.Checked = $RestartByDefault
$restartCheckBox.ForeColor = $Theme.Text
$restartCheckBox.BackColor = [System.Drawing.Color]::Transparent
$restartCheckBox.Font = $Font
+46 -1
View File
@@ -76,7 +76,8 @@ function New-DeployCenterUnattendXml {
[Parameter(Mandatory=$true)][System.Collections.IDictionary]$Profile,
[Parameter(Mandatory=$true)][System.Collections.IDictionary]$Configuration,
[Parameter(Mandatory=$true)][string]$HostName,
[Parameter(Mandatory=$true)][string]$Architecture
[Parameter(Mandatory=$true)][string]$Architecture,
[AllowEmptyString()][string]$WallpaperPath = ''
)
Test-DeployCenterUnattendConfiguration -Profile $Profile -Configuration $Configuration -HostName $HostName
@@ -114,6 +115,50 @@ function New-DeployCenterUnattendXml {
$node.InnerText = $values[$name]
}
}
$supportSettings = @(
@{ Name = 'SupportProvider'; Value = [string]$Configuration.UnattendSupportProvider },
@{ Name = 'SupportAppURL'; Value = [string]$Configuration.UnattendSupportAppURL }
)
$oemInformationPath = '/u:unattend/u:settings[@pass="oobeSystem"]/u:component[@name="Microsoft-Windows-Shell-Setup"]/u:OEMInformation'
foreach ($supportSetting in $supportSettings) {
$supportNode = $document.SelectSingleNode(($oemInformationPath + '/u:' + $supportSetting.Name), $namespaces)
if ($null -eq $supportNode) {
if (-not [string]::IsNullOrWhiteSpace($supportSetting.Value)) {
throw ('Le template du profil {0} ne definit pas le noeud {1}.' -f $Profile.Id, $supportSetting.Name)
}
continue
}
if ([string]::IsNullOrWhiteSpace($supportSetting.Value)) {
[void]$supportNode.ParentNode.RemoveChild($supportNode)
} else {
$supportNode.InnerText = $supportSetting.Value
}
}
$oemInformationNode = $document.SelectSingleNode($oemInformationPath, $namespaces)
if ($null -ne $oemInformationNode -and $oemInformationNode.SelectNodes('u:*', $namespaces).Count -eq 0) {
[void]$oemInformationNode.ParentNode.RemoveChild($oemInformationNode)
}
if (-not [string]::IsNullOrWhiteSpace($WallpaperPath)) {
$shellSetupNode = $document.SelectSingleNode('/u:unattend/u:settings[@pass="oobeSystem"]/u:component[@name="Microsoft-Windows-Shell-Setup"]', $namespaces)
if ($null -eq $shellSetupNode) { throw ('Le template du profil {0} ne definit pas le composant Shell-Setup dans oobeSystem.' -f $Profile.Id) }
$themesNode = $shellSetupNode.SelectSingleNode('u:Themes', $namespaces)
if ($null -eq $themesNode) {
$themesNode = $document.CreateElement('Themes', 'urn:schemas-microsoft-com:unattend')
[void]$shellSetupNode.AppendChild($themesNode)
}
foreach ($themeSetting in @(
@{ Name = 'ThemeName'; Value = 'Blorand' },
@{ Name = 'DesktopBackground'; Value = $WallpaperPath },
@{ Name = 'UWPAppsUseLightTheme'; Value = 'true' }
)) {
$themeNode = $themesNode.SelectSingleNode(('u:' + $themeSetting.Name), $namespaces)
if ($null -eq $themeNode) {
$themeNode = $document.CreateElement($themeSetting.Name, 'urn:schemas-microsoft-com:unattend')
[void]$themesNode.AppendChild($themeNode)
}
$themeNode.InnerText = [string]$themeSetting.Value
}
}
return $document.OuterXml
}