889 lines
40 KiB
PowerShell
889 lines
40 KiB
PowerShell
# DeployCenter - Interface WinPE
|
||
# Compatible Windows PowerShell 5.1
|
||
|
||
param(
|
||
# Affiche DeployCenter dans une fenetre redimensionnable pour le debug.
|
||
[switch]$Windowed,
|
||
[switch]$Vnc
|
||
)
|
||
|
||
$script:Windowed = [bool]$Windowed
|
||
$ErrorActionPreference = "Stop"
|
||
|
||
Add-Type -AssemblyName System.Windows.Forms
|
||
Add-Type -AssemblyName System.Drawing
|
||
[System.Windows.Forms.Application]::EnableVisualStyles()
|
||
|
||
Import-Module (Join-Path $PSScriptRoot "Modules\ThemeManager.psm1") -Force
|
||
$uiModulePath = Join-Path $PSScriptRoot 'Modules\UI.psm1'
|
||
if (-not (Test-Path -LiteralPath $uiModulePath -PathType Leaf)) { throw "Module UI introuvable : $uiModulePath" }
|
||
# Les workflows UI utilisent l'état de la session principale ; ce fichier est donc chargé dans ce scope.
|
||
. ([scriptblock]::Create([System.IO.File]::ReadAllText($uiModulePath)))
|
||
Import-Module (Join-Path $PSScriptRoot "Modules\Configuration.psm1") -Force
|
||
Import-Module (Join-Path $PSScriptRoot "Modules\HardwareInventory.psm1") -Force
|
||
|
||
# GroupBox dessine par DeployCenter pour que le fond et le cadre suivent les themes.
|
||
if (-not ([System.Management.Automation.PSTypeName]'DeployCenter.ThemedGroupBox').Type) {
|
||
Add-Type -TypeDefinition @'
|
||
using System;
|
||
using System.Drawing;
|
||
using System.Windows.Forms;
|
||
|
||
namespace DeployCenter {
|
||
public class ThemedGroupBox : GroupBox {
|
||
public Color PanelColor { get; set; }
|
||
public Color BorderColor { get; set; }
|
||
public Color TextColor { get; set; }
|
||
|
||
public ThemedGroupBox() {
|
||
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint |
|
||
ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
|
||
PanelColor = SystemColors.Control;
|
||
BorderColor = SystemColors.ControlDark;
|
||
TextColor = SystemColors.ControlText;
|
||
}
|
||
|
||
protected override void OnPaint(PaintEventArgs e) {
|
||
Graphics g = e.Graphics;
|
||
g.Clear(PanelColor);
|
||
Size textSize = TextRenderer.MeasureText(Text, Font);
|
||
int textLeft = 10;
|
||
int lineY = Math.Max(8, (int)Math.Ceiling(textSize.Height / 2.0));
|
||
using (Pen pen = new Pen(BorderColor)) {
|
||
g.DrawLine(pen, 0, lineY, textLeft - 2, lineY);
|
||
int afterText = textLeft + textSize.Width + 4;
|
||
if (afterText < Width - 2) g.DrawLine(pen, afterText, lineY, Width - 2, lineY);
|
||
g.DrawLine(pen, 0, lineY, 0, Height - 2);
|
||
g.DrawLine(pen, 0, Height - 2, Width - 2, Height - 2);
|
||
g.DrawLine(pen, Width - 2, lineY, Width - 2, Height - 2);
|
||
}
|
||
TextRenderer.DrawText(g, Text, Font, new Point(textLeft, 0), TextColor,
|
||
PanelColor, TextFormatFlags.NoPadding | TextFormatFlags.SingleLine);
|
||
}
|
||
}
|
||
}
|
||
'@ -ReferencedAssemblies System.Windows.Forms,System.Drawing
|
||
}
|
||
|
||
# ============================================================
|
||
# CHEMINS
|
||
# ============================================================
|
||
|
||
$script:DeployRoot = $PSScriptRoot
|
||
# Racine du lecteur qui heberge DeployCenter (ex. Y:\), sans lecteur code en dur.
|
||
$script:DeployVolumeRoot = $null
|
||
try {
|
||
$deployQualifier = Split-Path -Path $script:DeployRoot -Qualifier -ErrorAction Stop
|
||
if (-not [string]::IsNullOrWhiteSpace($deployQualifier)) {
|
||
$script:DeployVolumeRoot = $deployQualifier.TrimEnd('\') + '\'
|
||
}
|
||
} catch {
|
||
$script:DeployVolumeRoot = $null
|
||
}
|
||
$script:AssetsRoot = Join-Path $script:DeployRoot "Assets"
|
||
$script:LogoPath = Join-Path $script:AssetsRoot "logo.png"
|
||
$script:LogoDarkPath = Join-Path $script:AssetsRoot "logo-dark.png"
|
||
$script:LogRoot = Join-Path $script:DeployRoot "Logs"
|
||
|
||
# Détection réseau centralisée dans Modules\\Network.psm1.
|
||
$networkModulePath = Join-Path $PSScriptRoot "Modules\\Network.psm1"
|
||
if (-not (Test-Path -LiteralPath $networkModulePath -PathType Leaf)) {
|
||
throw "Module réseau introuvable : $networkModulePath"
|
||
}
|
||
. ([scriptblock]::Create([System.IO.File]::ReadAllText($networkModulePath)))
|
||
$script:DeployIPv4 = Get-DeployNetworkIPv4
|
||
|
||
# La gestion des journaux est centralisee dans Modules\\Logging.psm1.
|
||
$loggingModulePath = Join-Path $PSScriptRoot "Modules\\Logging.psm1"
|
||
if (-not (Test-Path -LiteralPath $loggingModulePath -PathType Leaf)) {
|
||
throw "Module de journalisation introuvable : $loggingModulePath"
|
||
}
|
||
. ([scriptblock]::Create([System.IO.File]::ReadAllText($loggingModulePath)))
|
||
Initialize-DeployCenterLogging -LogRoot $script:LogRoot -IPv4 $script:DeployIPv4
|
||
# Garder le scope du script principal pour que Write-Log reste résolu dans les callbacks WinForms.
|
||
$script:SourceLogAction = {
|
||
param($Message, $Level)
|
||
if ([string]::IsNullOrWhiteSpace([string]$Level)) { $Level = 'INFO' }
|
||
Write-Log -Message $Message -Level $Level
|
||
}
|
||
# Analyse des sources et des images Windows.
|
||
$windowsSourcesModulePath = Join-Path $script:DeployRoot 'Modules\WindowsSources.psm1'
|
||
if (-not (Test-Path -LiteralPath $windowsSourcesModulePath -PathType Leaf)) {
|
||
throw "Module de sources Windows introuvable : $windowsSourcesModulePath"
|
||
}
|
||
Import-Module $windowsSourcesModulePath -Force
|
||
|
||
# Les profils de partitionnement sont des fichiers de données PSD1, validés par leur module.
|
||
$partitioningModulePath = Join-Path $script:DeployRoot 'Modules\Partitioning.psm1'
|
||
if (-not (Test-Path -LiteralPath $partitioningModulePath -PathType Leaf)) {
|
||
throw "Module de partitionnement introuvable : $partitioningModulePath"
|
||
}
|
||
Import-Module $partitioningModulePath -Force
|
||
$deploymentModulePath = Join-Path $script:DeployRoot 'Modules\Deployment.psm1'
|
||
if (-not (Test-Path -LiteralPath $deploymentModulePath -PathType Leaf)) {
|
||
throw "Module de déploiement introuvable : $deploymentModulePath"
|
||
}
|
||
Import-Module $deploymentModulePath -Force
|
||
$unattendModulePath = Join-Path $script:DeployRoot 'Modules\Unattend.psm1'
|
||
if (-not (Test-Path -LiteralPath $unattendModulePath -PathType Leaf)) {
|
||
throw "Module Unattend introuvable : $unattendModulePath"
|
||
}
|
||
Import-Module $unattendModulePath -Force
|
||
$script:PartitionProfilesRoot = Join-Path $script:DeployRoot 'Partitioning\Profiles'
|
||
$script:PartitionProfiles = @()
|
||
foreach ($profileName in (Get-DeployCenterPartitionProfileNames -ProfilesRoot $script:PartitionProfilesRoot)) {
|
||
try {
|
||
$script:PartitionProfiles += Import-DeployCenterPartitionProfile -ProfilesRoot $script:PartitionProfilesRoot -ProfileName $profileName
|
||
} catch {
|
||
& $script:SourceLogAction "Profil de partitionnement '$profileName' ignoré : $($_.Exception.Message)" 'WARNING'
|
||
}
|
||
}
|
||
if ($script:PartitionProfiles.Count -eq 0) {
|
||
throw "Aucun profil de partitionnement valide trouvé dans $script:PartitionProfilesRoot"
|
||
}
|
||
$script:SelectedPartitionProfileIndex = 0
|
||
for ($profileIndex = 0; $profileIndex -lt $script:PartitionProfiles.Count; $profileIndex++) {
|
||
if ($script:PartitionProfiles[$profileIndex].Default -eq $true) {
|
||
$script:SelectedPartitionProfileIndex = $profileIndex
|
||
break
|
||
}
|
||
}
|
||
$script:SelectedPartitionProfile = $script:PartitionProfiles[$script:SelectedPartitionProfileIndex]
|
||
$script:SelectedPartitionSizing = $null
|
||
$script:SelectedDiskIndex = $null
|
||
$script:SelectedWindowsEdition = $null
|
||
$script:RestartAfterDeployment = $false
|
||
$script:RefreshingDiskList = $false
|
||
$script:ChangingPartitionProfileSelection = $false
|
||
|
||
# Inventaire de session et UltraVNC portable : tout reste dans le dossier temporaire.
|
||
$script:InventoryDir = Join-Path $env:TEMP 'DeployCenter'
|
||
$script:InventoryFile = Join-Path $script:InventoryDir 'DeployCenter_Inventory.json'
|
||
$script:VncPassword = $null
|
||
$script:VncDirectory = Join-Path $script:InventoryDir ("uvnc_{0}" -f $PID)
|
||
$script:VncProcess = $null
|
||
$script:VncStarted = $false
|
||
$script:HardwareInventory = $null
|
||
|
||
# ============================================================
|
||
# THEMES EXTERNES (Themes\*.psd1)
|
||
# Les thèmes sont des fichiers de données ; aucun code PowerShell n'est exécuté.
|
||
# ============================================================
|
||
|
||
$script:ThemesRoot = Join-Path $script:DeployRoot "Themes"
|
||
if (-not (Test-Path -LiteralPath $script:ThemesRoot -PathType Container)) {
|
||
New-Item -Path $script:ThemesRoot -ItemType Directory -Force | Out-Null
|
||
}
|
||
|
||
# ============================================================
|
||
# PREFERENCES (DeployCenter.ini en lecture seule : aucune ecriture automatique)
|
||
# ============================================================
|
||
|
||
$script:ConfigPath = Join-Path $script:DeployRoot "DeployCenter.ini"
|
||
|
||
# Themes par defaut : crees uniquement si absents, afin de faciliter les personnalisations.
|
||
$defaultThemeFiles = @{
|
||
Dark = @"
|
||
@{
|
||
Background = "#171A21"
|
||
Panel = "#222731"
|
||
PanelAlt = "#1C2029"
|
||
Text = "#F1F5F9"
|
||
Secondary = "#9CA9BC"
|
||
Accent = "#3B82F6"
|
||
Success = "#4ADE80"
|
||
Border = "#414A59"
|
||
Danger = "#EF4444"
|
||
Button = @{
|
||
Background = "#303744"; Foreground = "#F1F5F9"; Border = "#414A59"
|
||
HoverBackground = "#3B4555"; PressedBackground = "#485365"
|
||
DisabledBackground = "#292E38"; DisabledForeground = "#7F8999"
|
||
}
|
||
PrimaryButton = @{
|
||
Background = "#3B82F6"; Foreground = "#FFFFFF"; Border = "#3B82F6"
|
||
HoverBackground = "#2563EB"; PressedBackground = "#1D4ED8"
|
||
DisabledBackground = "#344A6A"; DisabledForeground = "#9AAAC1"
|
||
}
|
||
DangerButton = @{
|
||
Background = "#EF4444"; Foreground = "#FFFFFF"; Border = "#EF4444"
|
||
HoverBackground = "#DC2626"; PressedBackground = "#B91C1C"
|
||
DisabledBackground = "#59383B"; DisabledForeground = "#BBA0A2"
|
||
}
|
||
}
|
||
"@
|
||
Light = @"
|
||
@{
|
||
Background = "#F5F7FA"
|
||
Panel = "#FFFFFF"
|
||
PanelAlt = "#F8FAFC"
|
||
Text = "#1E293B"
|
||
Secondary = "#475569"
|
||
Accent = "#2563EB"
|
||
Success = "#16A34A"
|
||
Border = "#CBD5E1"
|
||
Danger = "#DC2626"
|
||
Button = @{
|
||
Background = "#E8EDF3"; Foreground = "#1E293B"; Border = "#CBD5E1"
|
||
HoverBackground = "#DCE4EE"; PressedBackground = "#CBD5E1"
|
||
DisabledBackground = "#F1F3F6"; DisabledForeground = "#94A3B8"
|
||
}
|
||
PrimaryButton = @{
|
||
Background = "#2563EB"; Foreground = "#FFFFFF"; Border = "#2563EB"
|
||
HoverBackground = "#1D4ED8"; PressedBackground = "#1E40AF"
|
||
DisabledBackground = "#C7D8F8"; DisabledForeground = "#F8FAFC"
|
||
}
|
||
DangerButton = @{
|
||
Background = "#DC2626"; Foreground = "#FFFFFF"; Border = "#DC2626"
|
||
HoverBackground = "#B91C1C"; PressedBackground = "#991B1B"
|
||
DisabledBackground = "#F2C5C5"; DisabledForeground = "#FFF7F7"
|
||
}
|
||
}
|
||
"@
|
||
}
|
||
foreach ($themeFileName in $defaultThemeFiles.Keys) {
|
||
$themeFilePath = Join-Path $script:ThemesRoot ($themeFileName + '.psd1')
|
||
if (-not (Test-Path -LiteralPath $themeFilePath -PathType Leaf)) {
|
||
Set-Content -LiteralPath $themeFilePath -Value $defaultThemeFiles[$themeFileName] -Encoding UTF8
|
||
}
|
||
}
|
||
|
||
$script:Config = Read-DeployCenterConfig -ConfigPath $script:ConfigPath
|
||
$script:UnattendProfilesRoot = Join-Path $script:DeployRoot 'Unattend\Profiles'
|
||
$script:UnattendProfiles = @()
|
||
foreach ($unattendProfileName in (Get-DeployCenterUnattendProfileNames -ProfilesRoot $script:UnattendProfilesRoot)) {
|
||
try {
|
||
$script:UnattendProfiles += Import-DeployCenterUnattendProfile `
|
||
-ProfilesRoot $script:UnattendProfilesRoot -ProfileName $unattendProfileName
|
||
} catch {
|
||
& $script:SourceLogAction "Profil Unattend '$unattendProfileName' ignoré : $($_.Exception.Message)" 'WARNING'
|
||
}
|
||
}
|
||
$duplicateUnattendNames = @($script:UnattendProfiles | Group-Object -Property Name | Where-Object Count -gt 1)
|
||
foreach ($duplicateName in $duplicateUnattendNames) {
|
||
& $script:SourceLogAction "Profils Unattend ignorés car leur nom affiché est en double : $($duplicateName.Name)." 'WARNING'
|
||
$script:UnattendProfiles = @($script:UnattendProfiles | Where-Object { [string]$_.Name -ne [string]$duplicateName.Name })
|
||
}
|
||
$script:UnattendOobeChoice = 'Avec OOBE'
|
||
foreach ($partitionProfile in $script:PartitionProfiles) {
|
||
foreach ($partition in $partitionProfile.Partitions) {
|
||
if ([string]$partition.Size.Policy -ne 'ConfiguredMB') { continue }
|
||
$configKey = [string]$partition.Size.ConfigKey
|
||
if (-not $script:Config.ContainsKey($configKey)) {
|
||
throw "Le paramètre DeployCenter.ini '$configKey' requis par le profil '$($partitionProfile.Name)' est absent de la configuration."
|
||
}
|
||
$configuredSizeMB = [int]$script:Config[$configKey]
|
||
if ($configuredSizeMB -le 0) {
|
||
throw "Le paramètre DeployCenter.ini '$configKey' doit être strictement positif."
|
||
}
|
||
$partition.Size.Value = $configuredSizeMB
|
||
$partition.Size.PreviewMB = $configuredSizeMB
|
||
}
|
||
}
|
||
$availableThemes = @(Get-DeployCenterThemeNames -ThemesRoot $script:ThemesRoot)
|
||
if ($availableThemes.Count -eq 0) { throw "Aucun thème valide trouvé dans $script:ThemesRoot" }
|
||
if ($availableThemes -notcontains $script:Config.Theme) { $script:Config.Theme = "Light" }
|
||
$script:CurrentTheme = $script:Config.Theme
|
||
try {
|
||
$script:Theme = Import-DeployCenterTheme -ThemesRoot $script:ThemesRoot -ThemeName $script:CurrentTheme
|
||
} catch {
|
||
$script:CurrentTheme = "Light"
|
||
$script:Config.Theme = "Light"
|
||
$script:Theme = Import-DeployCenterTheme -ThemesRoot $script:ThemesRoot -ThemeName "Light"
|
||
}
|
||
# ============================================================
|
||
# POLICES
|
||
# ============================================================
|
||
|
||
$script:FontRegular = [System.Drawing.Font]::new("Segoe UI", [single]10, [System.Drawing.FontStyle]::Regular)
|
||
$script:FontSmall = [System.Drawing.Font]::new("Segoe UI", [single]9, [System.Drawing.FontStyle]::Regular)
|
||
$script:FontTitle = [System.Drawing.Font]::new("Segoe UI", [single]23, [System.Drawing.FontStyle]::Bold)
|
||
$script:FontSubtitle = [System.Drawing.Font]::new("Segoe UI", [single]10, [System.Drawing.FontStyle]::Regular)
|
||
$script:FontGroup = [System.Drawing.Font]::new("Segoe UI", [single]11, [System.Drawing.FontStyle]::Bold)
|
||
|
||
# ============================================================
|
||
# RESEAU, ULTRAVNC ET INVENTAIRE DE SESSION
|
||
# ============================================================
|
||
|
||
|
||
|
||
|
||
# L'adresse IPv4 a été détectée par Modules\\Network.psm1 avant l'initialisation du journal.
|
||
|
||
# VNC est désactivé par défaut ; il démarre uniquement avec le paramètre -vnc.
|
||
$script:EnableVnc = [bool]$Vnc
|
||
if ($script:EnableVnc) {
|
||
try {
|
||
# Le code VNC est exécuté dans le scope principal uniquement avec -vnc.
|
||
$vncModulePath = Join-Path $PSScriptRoot "Modules\VNC.psm1"
|
||
if (-not (Test-Path -LiteralPath $vncModulePath -PathType Leaf)) {
|
||
throw "Module VNC introuvable : $vncModulePath"
|
||
}
|
||
$vncCode = [System.IO.File]::ReadAllText($vncModulePath)
|
||
. ([scriptblock]::Create($vncCode))
|
||
Start-DeployCenterVnc
|
||
} catch {
|
||
& $script:SourceLogAction "Impossible de démarrer VNC : $($_.Exception.Message)" 'ERROR'
|
||
}
|
||
} else {
|
||
& $script:SourceLogAction "UltraVNC non démarré : paramètre -vnc absent."
|
||
}
|
||
|
||
# ============================================================
|
||
# CREATION DES CONTROLES
|
||
# ============================================================
|
||
|
||
# ============================================================
|
||
# FENETRE PRINCIPALE
|
||
# ============================================================
|
||
|
||
$script:form = New-Object System.Windows.Forms.Form
|
||
$script:form.Text = "DeployCenter"
|
||
$script:form.BackColor = $script:Theme.Background
|
||
if ($script:Windowed) {
|
||
# Mode debug : fenetre classique, deplacable et reductible.
|
||
$script:form.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen
|
||
$script:form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::Sizable
|
||
$script:form.WindowState = [System.Windows.Forms.FormWindowState]::Normal
|
||
$script:form.TopMost = $false
|
||
$screen = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea
|
||
$debugWidth = [Math]::Min(1200, [Math]::Max(800, $screen.Width - 80))
|
||
$debugHeight = [Math]::Min(850, [Math]::Max(600, $screen.Height - 80))
|
||
$script:form.Size = New-Object System.Drawing.Size($debugWidth, $debugHeight)
|
||
} else {
|
||
# Mode normal : plein ecran, sans bordure et au premier plan.
|
||
$script:form.StartPosition = "Manual"
|
||
$script:form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::None
|
||
$script:form.WindowState = [System.Windows.Forms.FormWindowState]::Maximized
|
||
$script:form.TopMost = $true
|
||
$script:form.Bounds = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
|
||
}
|
||
$script:form.ForeColor = $script:Theme.Text
|
||
$script:form.Font = $script:FontRegular
|
||
$script:form.KeyPreview = $true
|
||
$script:form.MinimumSize = New-Object System.Drawing.Size(800, 600)
|
||
|
||
$screenWidth = $script:form.ClientSize.Width
|
||
$screenHeight = $script:form.ClientSize.Height
|
||
$margin = 30
|
||
$usableWidth = $screenWidth - (2 * $margin)
|
||
|
||
# ============================================================
|
||
# EN-TETE ET LOGO FACULTATIF
|
||
# ============================================================
|
||
|
||
$script:pictureLogo = $null
|
||
$titleX = 30
|
||
|
||
# Deux fichiers seulement : logo.png (clair et solution de repli) et logo-dark.png.
|
||
# En mode sombre, logo-dark.png est prioritaire ; s'il manque, logo.png est utilise.
|
||
# En mode clair, logo.png est utilise.
|
||
$initialLogoPath = Get-DeployCenterLogoPathForTheme -ThemeName $script:CurrentTheme `
|
||
-LogoPath $script:LogoPath -LogoDarkPath $script:LogoDarkPath
|
||
if ($null -ne $initialLogoPath) {
|
||
try {
|
||
$script:pictureLogo = New-Object System.Windows.Forms.PictureBox
|
||
$script:pictureLogo.Location = New-Object System.Drawing.Point(30, 20)
|
||
$script:pictureLogo.Size = New-Object System.Drawing.Size(64, 64)
|
||
$script:pictureLogo.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::Zoom
|
||
$script:pictureLogo.BackColor = [System.Drawing.Color]::Transparent
|
||
$script:pictureLogo.Image = [System.Drawing.Image]::FromFile($initialLogoPath)
|
||
$script:form.Controls.Add($script:pictureLogo)
|
||
$titleX = 110
|
||
}
|
||
catch {
|
||
$script:pictureLogo = $null
|
||
$titleX = 30
|
||
}
|
||
}
|
||
|
||
$script:lblTitle = New-Label -Text "DeployCenter" `
|
||
-X $titleX -Y 17 -Width 600 -Height 42 -Theme $script:Theme -Font $script:FontTitle `
|
||
-Color $script:Theme.Text
|
||
|
||
$script:lblSubtitle = New-Label `
|
||
-Text "Environnement de déploiement Windows" `
|
||
-X ($titleX + 4) -Y 61 -Width 650 -Height 24 -Theme $script:Theme -Font $script:FontSubtitle `
|
||
-Color $script:Theme.Secondary
|
||
|
||
$script:form.Controls.Add($script:lblTitle)
|
||
$script:form.Controls.Add($script:lblSubtitle)
|
||
|
||
# Menu de selection du theme ; les noms correspondent aux fichiers Themes\<Nom>.psd1
|
||
$script:cmbTheme = New-Object System.Windows.Forms.ComboBox
|
||
$script:cmbTheme.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList
|
||
# OwnerDraw permet de colorer aussi la liste deroulante, que WinForms laisse sinon au theme systeme.
|
||
$script:cmbTheme.DrawMode = [System.Windows.Forms.DrawMode]::OwnerDrawFixed
|
||
$script:cmbTheme.ItemHeight = 24
|
||
$script:cmbTheme.Font = $script:FontRegular
|
||
$script:cmbTheme.Width = 190
|
||
$script:cmbTheme.Height = 32
|
||
$script:cmbTheme.Location = New-Object System.Drawing.Point(0, 29)
|
||
$script:cmbTheme.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Right
|
||
foreach ($themeName in (Get-DeployCenterThemeNames -ThemesRoot $script:ThemesRoot)) { [void]$script:cmbTheme.Items.Add($themeName) }
|
||
$script:cmbTheme.SelectedItem = $script:CurrentTheme
|
||
$script:cmbTheme.BackColor = $script:Theme.Panel
|
||
$script:cmbTheme.ForeColor = $script:Theme.Text
|
||
$script:cmbTheme.Add_DrawItem({
|
||
param($sender, $e)
|
||
if ($e.Index -lt 0) {
|
||
$itemText = [string]$sender.Text
|
||
} else {
|
||
$itemText = [string]$sender.Items[$e.Index]
|
||
}
|
||
$isSelected = (($e.State -band [System.Windows.Forms.DrawItemState]::Selected) -ne 0)
|
||
if ($isSelected) {
|
||
$backgroundColor = $script:Theme.Accent
|
||
$foregroundColor = [System.Drawing.Color]::White
|
||
} else {
|
||
$backgroundColor = $script:Theme.Panel
|
||
$foregroundColor = $script:Theme.Text
|
||
}
|
||
$backgroundBrush = New-Object System.Drawing.SolidBrush($backgroundColor)
|
||
try { $e.Graphics.FillRectangle($backgroundBrush, $e.Bounds) }
|
||
finally { $backgroundBrush.Dispose() }
|
||
if (-not [string]::IsNullOrEmpty($itemText)) {
|
||
$textBounds = $e.Bounds
|
||
$textBounds.X += 4
|
||
[System.Windows.Forms.TextRenderer]::DrawText(
|
||
$e.Graphics, $itemText, $sender.Font, $textBounds, $foregroundColor,
|
||
([System.Windows.Forms.TextFormatFlags]::Left -bor [System.Windows.Forms.TextFormatFlags]::VerticalCenter -bor [System.Windows.Forms.TextFormatFlags]::EndEllipsis)
|
||
)
|
||
}
|
||
$e.DrawFocusRectangle()
|
||
})
|
||
$script:form.Controls.Add($script:cmbTheme)
|
||
$script:cmbTheme.BringToFront()
|
||
|
||
# ============================================================
|
||
# INFORMATIONS DU PC
|
||
# ============================================================
|
||
|
||
$script:groupPC = New-GroupBox -Text "Informations du PC" `
|
||
-X $margin -Y 100 -Width $usableWidth -Height 90 -Theme $script:Theme -Font $script:FontGroup
|
||
|
||
$script:lblManufacturer = New-Label -Text "Fabricant : -" `
|
||
-X 18 -Y 25 -Width 330 -Height 24 -Theme $script:Theme -Font $script:FontRegular
|
||
$script:lblModel = New-Label -Text "Modèle : -" `
|
||
-X 360 -Y 25 -Width 400 -Height 24 -Theme $script:Theme -Font $script:FontRegular
|
||
$script:lblSerial = New-Label -Text "Numéro de série : -" `
|
||
-X 18 -Y 52 -Width 330 -Height 24 -Theme $script:Theme -Font $script:FontRegular
|
||
$script:lblFirmware = New-Label -Text "Firmware : -" `
|
||
-X 360 -Y 52 -Width 220 -Height 24 -Theme $script:Theme -Font $script:FontRegular
|
||
$script:lblArchitecture = New-Label -Text "Architecture : -" `
|
||
-X 600 -Y 52 -Width 220 -Height 24 -Theme $script:Theme -Font $script:FontRegular
|
||
$script:groupPC.Controls.AddRange(@(
|
||
$script:lblManufacturer,
|
||
$script:lblModel,
|
||
$script:lblSerial,
|
||
$script:lblFirmware,
|
||
$script:lblArchitecture
|
||
))
|
||
$script:form.Controls.Add($script:groupPC)
|
||
|
||
# ============================================================
|
||
# PREPARATION DU DEPLOIEMENT
|
||
# ============================================================
|
||
|
||
$script:groupDisks = New-GroupBox -Text "Préparation du déploiement" `
|
||
-X $margin -Y 205 -Width $usableWidth -Height 270 -Theme $script:Theme -Font $script:FontGroup
|
||
|
||
$deploymentControls = New-DeployCenterDeploymentControls `
|
||
-Parent $script:groupDisks `
|
||
-ProfileNames @($script:PartitionProfiles | ForEach-Object { [string]$_.Name }) `
|
||
-Theme $script:Theme `
|
||
-Font $script:FontSmall
|
||
$script:cmbDisk = $deploymentControls.DiskComboBox
|
||
$script:btnChooseWindows = $deploymentControls.ChooseSystemButton
|
||
$script:lblSelectedWindows = $deploymentControls.SelectedSystemLabel
|
||
$script:lblPartitionProfile = $deploymentControls.PartitionProfileLabel
|
||
$script:cmbPartitionProfile = $deploymentControls.PartitionProfileComboBox
|
||
$script:cmbUnattendProfile = $deploymentControls.UnattendProfileComboBox
|
||
$script:DeploymentControls = $deploymentControls
|
||
$script:lblHostName = $deploymentControls.HostNameLabel
|
||
$script:txtHostName = $deploymentControls.HostNameTextBox
|
||
$script:cmbPartitionProfile.SelectedIndex = $script:SelectedPartitionProfileIndex
|
||
|
||
$script:form.Controls.Add($script:groupDisks)
|
||
|
||
|
||
|
||
# ============================================================
|
||
# JOURNAL DANS UNE FENETRE DEDIEE
|
||
# ============================================================
|
||
|
||
$logWindow = New-DeployCenterLogWindow -Theme $script:Theme -Font $script:FontRegular
|
||
$script:logForm = $logWindow.Form
|
||
$script:txtLog = $logWindow.TextBox
|
||
|
||
$buttonHeight = 38
|
||
# En plein ecran, rapprocher les boutons du bas sans empiéter sur le pied de page.
|
||
# En mode fenetre, conserver la position actuelle.
|
||
$buttonY = if ($script:Windowed) {
|
||
$screenHeight - 54 - $buttonHeight
|
||
} else {
|
||
$screenHeight - 42 - $buttonHeight
|
||
}
|
||
# BOUTONS JOURNAL, ACTUALISER ET FERMER
|
||
# ============================================================
|
||
|
||
$buttonWidth = 140
|
||
$buttonGap = 12
|
||
$closeX = $screenWidth - $margin - $buttonWidth
|
||
$deployX = $closeX - $buttonGap - $buttonWidth
|
||
$refreshX = $deployX - $buttonGap - $buttonWidth
|
||
$script:btnLog = New-Button -Text "Journal" `
|
||
-X $margin -Y $buttonY -Width $buttonWidth -Height $buttonHeight `
|
||
-Theme $script:Theme -Font $script:FontRegular `
|
||
-Role "Button"
|
||
|
||
$script:btnRefresh = New-Button -Text "Actualiser" `
|
||
-X $refreshX -Y $buttonY -Width $buttonWidth -Height $buttonHeight `
|
||
-Theme $script:Theme -Font $script:FontRegular `
|
||
-Role "PrimaryButton"
|
||
|
||
$script:btnDeploy = New-Button -Text "Installer" `
|
||
-X $deployX -Y $buttonY -Width $buttonWidth -Height $buttonHeight `
|
||
-Theme $script:Theme -Font $script:FontRegular `
|
||
-Role "PrimaryButton"
|
||
|
||
$script:btnClose = New-Button -Text "Fermer" `
|
||
-X $closeX -Y $buttonY -Width $buttonWidth -Height $buttonHeight `
|
||
-Theme $script:Theme -Font $script:FontRegular `
|
||
-Role "DangerButton"
|
||
|
||
$script:form.Controls.Add($script:btnLog)
|
||
$script:form.Controls.Add($script:btnRefresh)
|
||
$script:form.Controls.Add($script:btnDeploy)
|
||
$script:form.Controls.Add($script:btnClose)
|
||
Add-SessionFooter -TargetForm $script:form -Theme $script:Theme -Font $script:FontSmall `
|
||
-IPv4 $script:DeployIPv4 -VncPassword $script:VncPassword -ShowPassword $true
|
||
|
||
# ============================================================
|
||
# APPLICATION DU THEME A TOUS LES CONTROLES
|
||
# ============================================================
|
||
|
||
|
||
|
||
|
||
|
||
# ============================================================
|
||
# DETECTION DES SOURCES WINDOWS SUR PARTAGE SMB
|
||
# ============================================================
|
||
|
||
|
||
|
||
# ============================================================
|
||
# INVENTAIRE MATERIEL
|
||
# ============================================================
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
# ============================================================
|
||
# MISE EN PAGE ADAPTATIVE
|
||
# Les grandes zones suivent la fenetre ; les marges et hauteurs de controles restent fixes.
|
||
# ============================================================
|
||
|
||
|
||
|
||
# ============================================================
|
||
# EVENEMENTS
|
||
# ============================================================
|
||
|
||
$script:btnChooseWindows.Add_Click({
|
||
Show-WindowsSourcesDialog
|
||
if ($script:SelectedWindowsEdition) {
|
||
$edition = $script:SelectedWindowsEdition
|
||
$sourceDescription = if ($edition.ImagePath) { [string]$edition.ImagePath } else { [string]$edition.SourcePath }
|
||
$script:lblSelectedWindows.Text = "{0} (index {1}) — {2}" -f $edition.Name, $edition.Index, $sourceDescription
|
||
$script:lblSelectedWindows.ForeColor = $script:Theme.Success
|
||
$script:lblSelectedWindows.Name = 'lblSelectedWindows'
|
||
$script:cmbPartitionProfile.Enabled = $true
|
||
Set-DeployCenterUnattendProfileChoices -ComboBox $script:cmbUnattendProfile `
|
||
-Profiles $script:UnattendProfiles -EditionName ([string]$edition.Name) `
|
||
-OobeChoice $script:UnattendOobeChoice
|
||
}
|
||
})
|
||
|
||
$script:cmbUnattendProfile.Add_SelectedIndexChanged({
|
||
$showHostName = $script:cmbUnattendProfile.SelectedItem -and
|
||
[string]$script:cmbUnattendProfile.SelectedItem -ne $script:UnattendOobeChoice
|
||
Set-DeployCenterUnattendHostNameVisibility -Controls $script:DeploymentControls -ShowHostName ([bool]$showHostName)
|
||
})
|
||
|
||
$script:btnLog.Add_Click({
|
||
if ($script:logForm.IsDisposed) { return }
|
||
if (-not $script:logForm.Visible) { $script:logForm.Show($script:form) }
|
||
$script:logForm.BringToFront()
|
||
})
|
||
|
||
$script:btnRefresh.Add_Click({
|
||
Update-HardwareView
|
||
})
|
||
|
||
$script:btnDeploy.Add_Click({
|
||
$diskIndex = $null
|
||
if ($null -ne $script:cmbDisk.SelectedItem) { $diskIndex = [int]$script:cmbDisk.SelectedItem.Tag }
|
||
$diskInfo = if ($null -ne $diskIndex) { Get-SelectedDeployDiskInfo -HardwareInfo $script:HardwareInventory -DiskIndex $diskIndex } else { $null }
|
||
$unattendChoice = [string]$script:cmbUnattendProfile.SelectedItem
|
||
$unattendProfile = $null
|
||
$hostName = $null
|
||
if ($unattendChoice -and $unattendChoice -ne $script:UnattendOobeChoice) {
|
||
$matchingProfiles = @($script:UnattendProfiles | Where-Object { [string]$_.Name -eq $unattendChoice })
|
||
if ($matchingProfiles.Count -ne 1) {
|
||
Show-DeployCenterMessage -Message "Le profil Unattend '$unattendChoice' est introuvable ou ambigu." -Title 'Profil Unattend' -Icon Error -Owner $script:form -Theme $script:Theme -Font $script:FontRegular
|
||
return
|
||
}
|
||
$unattendProfile = $matchingProfiles[0]
|
||
$hostName = [string]$script:txtHostName.Text.Trim()
|
||
}
|
||
|
||
if ($null -eq $diskInfo) {
|
||
Show-DeployCenterMessage -Message 'Sélectionne le disque de destination.' -Title 'Déploiement Windows' -Icon Warning -Owner $script:form -Theme $script:Theme -Font $script:FontRegular
|
||
return
|
||
}
|
||
if ($null -eq $script:SelectedWindowsEdition) {
|
||
Show-DeployCenterMessage -Message 'Sélectionne une édition Windows à installer.' -Title 'Déploiement Windows' -Icon Warning -Owner $script:form -Theme $script:Theme -Font $script:FontRegular
|
||
return
|
||
}
|
||
if ($null -ne $unattendProfile -and $unattendProfile.ComputerName -and $hostName -notmatch '^(?=.*[A-Za-z])[A-Za-z0-9](?:[A-Za-z0-9-]{0,13}[A-Za-z0-9])?$') {
|
||
Show-DeployCenterMessage -Message "Le nom d’hôte doit contenir de 1 à 15 caractères, commencer et finir par une lettre ou un chiffre, et ne contenir que des lettres, chiffres ou tirets." -Title "Nom d’hôte invalide" -Icon Warning -Owner $script:form -Theme $script:Theme -Font $script:FontRegular
|
||
return
|
||
}
|
||
if ($null -ne $unattendProfile) {
|
||
try {
|
||
Test-DeployCenterUnattendConfiguration -Profile $unattendProfile `
|
||
-Configuration $script:Config -HostName $hostName
|
||
} catch {
|
||
Show-DeployCenterMessage -Message $_.Exception.Message -Title 'Configuration Unattend invalide' -Icon Warning -Owner $script:form -Theme $script:Theme -Font $script:FontRegular
|
||
return
|
||
}
|
||
}
|
||
if ($script:SelectedPartitionSizing -and [int]$script:SelectedPartitionSizing.DiskIndex -ne [int]$diskInfo.Index) {
|
||
Show-DeployCenterMessage -Message 'La taille des partitions correspond à un autre disque. Sélectionne de nouveau le profil de partitionnement.' -Title 'Partitionnement' -Icon Warning -Owner $script:form -Theme $script:Theme -Font $script:FontRegular
|
||
return
|
||
}
|
||
|
||
$sizeDescription = 'Tailles définies par le profil'
|
||
if ($script:SelectedPartitionSizing -and $script:SelectedPartitionSizing.Inputs.Count -gt 0) {
|
||
$sizeParts = @()
|
||
foreach ($role in $script:SelectedPartitionSizing.Inputs.Keys) {
|
||
$sizeParts += ("{0} : {1} Go" -f $role, $script:SelectedPartitionSizing.Inputs[$role])
|
||
}
|
||
$sizeParts += ("espace restant : {0:N1} Go" -f $script:SelectedPartitionSizing.RemainderGB)
|
||
$sizeDescription = $sizeParts -join ', '
|
||
}
|
||
$unattendDescription = if ($null -ne $unattendProfile) { "Profil Unattend : $($unattendProfile.Name)`r`nNom d’hôte : $hostName" } else { 'Configuration initiale : Avec OOBE' }
|
||
$confirmation = Show-DeployCenterConfirmation `
|
||
-Title "Confirmer l’effacement du disque" `
|
||
-Message ("Disque {0} — {1} ({2:N1} Go)`r`nProfil de partitionnement : {3}`r`nÉdition : {4}`r`nTailles : {5}`r`n{6}`r`nTout le contenu du disque sera effacé. Cette opération est irréversible." -f $diskInfo.Index, $diskInfo.Model, $diskInfo.SizeGB, $script:SelectedPartitionProfile.Name, $script:SelectedWindowsEdition.Name, $sizeDescription, $unattendDescription) `
|
||
-Owner $script:form -Theme $script:Theme -Font $script:FontRegular
|
||
if (-not $confirmation) { return }
|
||
|
||
$progress = New-DeployCenterDeploymentProgress -Theme $script:Theme -Font $script:FontRegular
|
||
$script:form.Enabled = $false
|
||
try {
|
||
$progress.Form.Show($script:form)
|
||
[System.Windows.Forms.Application]::DoEvents()
|
||
$deploymentLogAction = $script:SourceLogAction
|
||
$deploymentProgressMessage = 'Préparation du déploiement…'
|
||
$deploymentProgressAction = {
|
||
param($Message, $Percent)
|
||
if ($null -ne $Message) {
|
||
$deploymentProgressMessage = [string]$Message
|
||
if ($null -eq $Percent) {
|
||
$progress.ProgressBar.Style = [System.Windows.Forms.ProgressBarStyle]::Marquee
|
||
}
|
||
if ($deploymentLogAction -is [scriptblock]) {
|
||
& $deploymentLogAction ([string]$Message) 'INFO'
|
||
}
|
||
}
|
||
if ($null -ne $Percent) {
|
||
if ($progress.ProgressBar.Style -ne [System.Windows.Forms.ProgressBarStyle]::Continuous) {
|
||
$progress.ProgressBar.Style = [System.Windows.Forms.ProgressBarStyle]::Continuous
|
||
}
|
||
$progress.ProgressBar.Value = [int][Math]::Max(0, [Math]::Min(100, $Percent))
|
||
$progress.StatusLabel.Text = '{0} ({1} %)' -f $deploymentProgressMessage, $progress.ProgressBar.Value
|
||
} elseif ($null -ne $Message) {
|
||
$progress.StatusLabel.Text = $deploymentProgressMessage
|
||
}
|
||
[System.Windows.Forms.Application]::DoEvents()
|
||
}.GetNewClosure()
|
||
|
||
Invoke-DeployCenterWindowsDeployment `
|
||
-DiskInfo $diskInfo `
|
||
-Profile $script:SelectedPartitionProfile `
|
||
-SizingState $script:SelectedPartitionSizing `
|
||
-Edition $script:SelectedWindowsEdition `
|
||
-HostName $hostName `
|
||
-UnattendProfile $unattendProfile `
|
||
-UnattendConfiguration $script:Config `
|
||
-Firmware $script:HardwareInventory.Firmware `
|
||
-TemporaryRoot $script:InventoryDir `
|
||
-LogAction $script:SourceLogAction `
|
||
-ProgressAction $deploymentProgressAction
|
||
|
||
$progress.Form.Close()
|
||
$script:form.Enabled = $true
|
||
$restartAfterDeployment = Show-DeployCenterDeploymentComplete `
|
||
-Message 'Windows a été appliqué avec succès. Le déploiement est prêt.' `
|
||
-Owner $script:form -Theme $script:Theme -Font $script:FontRegular
|
||
if ($restartAfterDeployment) {
|
||
$script:RestartAfterDeployment = $true
|
||
$script:form.Close()
|
||
}
|
||
} catch {
|
||
if (-not $progress.Form.IsDisposed) { $progress.Form.Close() }
|
||
$script:form.Enabled = $true
|
||
& $script:SourceLogAction "Échec du déploiement : $($_.Exception.Message)" 'ERROR'
|
||
Show-DeployCenterMessage -Message $_.Exception.Message -Title 'Échec du déploiement' -Icon Error -Owner $script:form -Theme $script:Theme -Font $script:FontRegular
|
||
} finally {
|
||
if (-not $progress.Form.IsDisposed) { $progress.Form.Dispose() }
|
||
$script:form.Enabled = $true
|
||
if (-not $script:form.IsDisposed -and $script:form.Visible) { $script:form.Activate() }
|
||
}
|
||
})
|
||
|
||
$script:btnClose.Add_Click({
|
||
$script:form.Close()
|
||
})
|
||
|
||
$script:cmbTheme.Add_SelectedIndexChanged({
|
||
if ($script:cmbTheme.SelectedItem) {
|
||
Set-DeployCenterTheme -ThemeName ([string]$script:cmbTheme.SelectedItem)
|
||
}
|
||
})
|
||
|
||
$script:cmbDisk.Add_SizeChanged({
|
||
Set-DiskSelectorWidth
|
||
})
|
||
|
||
$script:cmbPartitionProfile.Add_SelectedIndexChanged({
|
||
if ($script:ChangingPartitionProfileSelection) { return }
|
||
$selectedIndex = $script:cmbPartitionProfile.SelectedIndex
|
||
if ($selectedIndex -ge 0 -and $selectedIndex -lt $script:PartitionProfiles.Count) {
|
||
$candidateProfile = $script:PartitionProfiles[$selectedIndex]
|
||
$sizeInputs = @($candidateProfile.Partitions | Where-Object { $_.Size.Policy -eq 'UserInputGB' })
|
||
if ($sizeInputs.Count -gt 0) {
|
||
$selectedDiskTag = if ($null -ne $script:cmbDisk.SelectedItem) { [int]$script:cmbDisk.SelectedItem.Tag } else { $null }
|
||
$diskInfo = if ($null -ne $selectedDiskTag) { Get-SelectedDeployDiskInfo -HardwareInfo $script:HardwareInventory -DiskIndex $selectedDiskTag } else { $null }
|
||
$initialValues = @{}
|
||
if ($script:SelectedPartitionSizing -and $script:SelectedPartitionSizing.ProfileId -eq $candidateProfile.Id) {
|
||
$initialValues = $script:SelectedPartitionSizing.Inputs
|
||
}
|
||
if ($null -eq $diskInfo) {
|
||
Show-DeployCenterMessage -Message "Sélectionne d’abord un disque physique." -Title 'Partitionnement' -Icon Information -Owner $script:form -Theme $script:Theme -Font $script:FontRegular
|
||
}
|
||
if ($null -eq $diskInfo -or -not (Set-PartitionProfileSizingSelection -Profile $candidateProfile -DiskInfo $diskInfo -InitialValues $initialValues)) {
|
||
$script:ChangingPartitionProfileSelection = $true
|
||
try { $script:cmbPartitionProfile.SelectedIndex = $script:SelectedPartitionProfileIndex }
|
||
finally { $script:ChangingPartitionProfileSelection = $false }
|
||
return
|
||
}
|
||
} else {
|
||
$script:SelectedPartitionSizing = $null
|
||
}
|
||
|
||
$script:SelectedPartitionProfileIndex = $selectedIndex
|
||
$script:SelectedPartitionProfile = $candidateProfile
|
||
& $script:SourceLogAction "Profil de partitionnement sélectionné : $($candidateProfile.Name)" 'INFO'
|
||
if ($script:SelectedPartitionSizing) {
|
||
foreach ($role in $script:SelectedPartitionSizing.Inputs.Keys) {
|
||
& $script:SourceLogAction "Taille saisie pour $role : $($script:SelectedPartitionSizing.Inputs[$role]) Go ; espace restant : $($script:SelectedPartitionSizing.RemainderGB) Go" 'INFO'
|
||
}
|
||
}
|
||
}
|
||
})
|
||
|
||
$script:cmbDisk.Add_SelectedIndexChanged({
|
||
if ($script:RefreshingDiskList -or $script:ChangingPartitionProfileSelection) { return }
|
||
$selectedDiskTag = if ($null -ne $script:cmbDisk.SelectedItem) { [int]$script:cmbDisk.SelectedItem.Tag } else { $null }
|
||
$diskInfo = if ($null -ne $selectedDiskTag) { Get-SelectedDeployDiskInfo -HardwareInfo $script:HardwareInventory -DiskIndex $selectedDiskTag } else { $null }
|
||
if ($null -eq $diskInfo) { $script:SelectedDiskIndex = $null; return }
|
||
|
||
$profileSizeInputs = @($script:SelectedPartitionProfile.Partitions | Where-Object { $_.Size.Policy -eq 'UserInputGB' })
|
||
if ($profileSizeInputs.Count -gt 0) {
|
||
$initialValues = if ($script:SelectedPartitionSizing -and $script:SelectedPartitionSizing.ProfileId -eq $script:SelectedPartitionProfile.Id) {
|
||
$script:SelectedPartitionSizing.Inputs
|
||
} else { @{} }
|
||
if (-not (Set-PartitionProfileSizingSelection -Profile $script:SelectedPartitionProfile -DiskInfo $diskInfo -InitialValues $initialValues)) {
|
||
$script:RefreshingDiskList = $true
|
||
try {
|
||
for ($i = 0; $i -lt $script:cmbDisk.Items.Count; $i++) {
|
||
if ([string]$script:cmbDisk.Items[$i].Tag -eq [string]$script:SelectedDiskIndex) { $script:cmbDisk.SelectedIndex = $i; break }
|
||
}
|
||
} finally { $script:RefreshingDiskList = $false }
|
||
return
|
||
}
|
||
}
|
||
$script:SelectedDiskIndex = [string]$diskInfo.Index
|
||
})
|
||
|
||
$script:form.Add_SizeChanged({
|
||
Update-DeployCenterLayout
|
||
})
|
||
|
||
$script:form.Add_KeyDown({
|
||
param($sender, $eventArgs)
|
||
|
||
if ($eventArgs.KeyCode -eq [System.Windows.Forms.Keys]::Escape) {
|
||
$script:form.Close()
|
||
}
|
||
elseif ($eventArgs.KeyCode -eq [System.Windows.Forms.Keys]::F5) {
|
||
Update-HardwareView
|
||
}
|
||
})
|
||
|
||
$script:form.Add_Shown({
|
||
# Use the real maximized client width to position the theme button.
|
||
Update-DeployCenterLayout
|
||
$script:cmbTheme.BringToFront()
|
||
& $script:SourceLogAction "DeployCenter demarre."
|
||
& $script:SourceLogAction "Dossier : $script:DeployRoot"
|
||
& $script:SourceLogAction "Journal : $script:LogFile"
|
||
Update-HardwareView
|
||
})
|
||
|
||
$script:form.Add_FormClosed({
|
||
if ($null -ne $script:pictureLogo -and $null -ne $script:pictureLogo.Image) {
|
||
$script:pictureLogo.Image.Dispose()
|
||
}
|
||
|
||
$script:FontRegular.Dispose()
|
||
$script:FontSmall.Dispose()
|
||
$script:FontTitle.Dispose()
|
||
$script:FontSubtitle.Dispose()
|
||
$script:FontGroup.Dispose()
|
||
})
|
||
|
||
# ============================================================
|
||
# LANCEMENT
|
||
# ============================================================
|
||
|
||
try {
|
||
[void]$script:form.ShowDialog()
|
||
}
|
||
finally {
|
||
if ($script:SelectedWindowsEdition -and $script:SelectedWindowsEdition.MountedImage) {
|
||
try { [void](Dismount-DeployCenterInstallImage -Image $script:SelectedWindowsEdition) } catch {
|
||
& $script:SourceLogAction "Impossible de démonter l'ISO à la fermeture : $($_.Exception.Message)" 'WARNING'
|
||
}
|
||
}
|
||
if ($script:EnableVnc -and (Get-Command Stop-DeployCenterVnc -ErrorAction SilentlyContinue)) {
|
||
Stop-DeployCenterVnc
|
||
}
|
||
$script:form.Dispose()
|
||
if ($script:RestartAfterDeployment) {
|
||
try {
|
||
Restart-DeployCenterWinPE -LogAction $script:SourceLogAction
|
||
} catch {
|
||
& $script:SourceLogAction "Échec de la demande de redémarrage : $($_.Exception.Message)" 'ERROR'
|
||
}
|
||
}
|
||
}
|