Ajout de la configuration de paritionnement des disques
This commit is contained in:
1 parent
7c724d475e
commit
e388cdca45
9 files changed
+450
-123
No files matched your search
+3
-1
@@ -1 +1,3 @@
|
||||
Logs/*
|
||||
Logs/*
|
||||
Archives v1/*
|
||||
Archives v2/*
|
||||
+84
-22
@@ -96,7 +96,33 @@ if (-not (Test-Path -LiteralPath $loggingModulePath -PathType Leaf)) {
|
||||
}
|
||||
. ([scriptblock]::Create([System.IO.File]::ReadAllText($loggingModulePath)))
|
||||
Initialize-DeployCenterLogging -LogRoot $script:LogRoot -IPv4 $script:DeployIPv4
|
||||
$script:HardwareJson = Join-Path $env:TEMP "HardwareInfo.json"
|
||||
|
||||
# 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
|
||||
$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 {
|
||||
Write-Log "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]
|
||||
|
||||
# Inventaire de session et UltraVNC portable : tout reste dans le dossier temporaire.
|
||||
$script:InventoryDir = Join-Path $env:TEMP 'DeployCenter'
|
||||
@@ -262,6 +288,21 @@ function Write-DeployInventory {
|
||||
}
|
||||
$json = $inventory | ConvertTo-Json -Depth 8
|
||||
Set-Content -LiteralPath $script:InventoryFile -Value $json -Encoding UTF8
|
||||
|
||||
# Nettoyer les anciens exports séparés après l'écriture de l'inventaire consolidé.
|
||||
$legacyInventoryFiles = @(
|
||||
(Join-Path $env:TEMP 'HardwareInfo.json'),
|
||||
(Join-Path $script:InventoryDir 'hardware.json')
|
||||
)
|
||||
foreach ($legacyFile in $legacyInventoryFiles) {
|
||||
if (Test-Path -LiteralPath $legacyFile -PathType Leaf) {
|
||||
try {
|
||||
Remove-Item -LiteralPath $legacyFile -Force -ErrorAction Stop
|
||||
} catch {
|
||||
Write-Log "Impossible de supprimer l'ancien export d'inventaire '$legacyFile' : $($_.Exception.Message)" 'WARNING'
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Write-Log "Impossible d'écrire l'inventaire temporaire : $($_.Exception.Message)" 'WARNING'
|
||||
}
|
||||
@@ -611,13 +652,13 @@ $script:form.Controls.Add($script:groupPC)
|
||||
# DISQUE PHYSIQUE - SELECTEUR COMPACT
|
||||
# ============================================================
|
||||
|
||||
$script:groupDisks = New-GroupBox -Text "Disque physique" `
|
||||
-X $margin -Y 220 -Width $usableWidth -Height 78
|
||||
$script:groupDisks = New-GroupBox -Text "Disque et partitionnement" `
|
||||
-X $margin -Y 220 -Width $usableWidth -Height 116
|
||||
|
||||
$script:cmbDisk = New-Object System.Windows.Forms.ComboBox
|
||||
$script:cmbDisk.Name = "cmbDisk"
|
||||
$script:cmbDisk.Location = New-Object System.Drawing.Point(12, 30)
|
||||
$script:cmbDisk.Size = New-Object System.Drawing.Size(($usableWidth - 24), 28)
|
||||
$script:cmbDisk.Location = New-Object System.Drawing.Point(12, 38)
|
||||
$script:cmbDisk.Size = New-Object System.Drawing.Size(($usableWidth - 24), 26)
|
||||
$script:cmbDisk.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right
|
||||
$script:cmbDisk.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList
|
||||
$script:cmbDisk.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
|
||||
@@ -626,13 +667,29 @@ $script:cmbDisk.ForeColor = $script:Theme.Text
|
||||
$script:cmbDisk.Font = $script:FontSmall
|
||||
$script:cmbDisk.IntegralHeight = $false
|
||||
$script:cmbDisk.MaxDropDownItems = 12
|
||||
|
||||
$partitionProfileSelector = New-DeployCenterPartitionProfileSelector `
|
||||
-Parent $script:groupDisks `
|
||||
-ProfileNames @($script:PartitionProfiles | ForEach-Object { [string]$_.Name }) `
|
||||
-Theme $script:Theme `
|
||||
-Font $script:FontSmall
|
||||
$script:lblPartitionProfile = $partitionProfileSelector.Label
|
||||
$script:cmbPartitionProfile = $partitionProfileSelector.ComboBox
|
||||
$script:cmbPartitionProfile.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right
|
||||
$script:cmbPartitionProfile.SelectedIndex = $script:SelectedPartitionProfileIndex
|
||||
|
||||
$script:groupDisks.Controls.Add($script:cmbDisk)
|
||||
$script:form.Controls.Add($script:groupDisks)
|
||||
|
||||
function Set-DiskSelectorWidth {
|
||||
if ($null -eq $script:cmbDisk -or $null -eq $script:groupDisks) { return }
|
||||
$script:cmbDisk.Location = New-Object System.Drawing.Point(12, 30)
|
||||
$script:cmbDisk.Size = New-Object System.Drawing.Size([Math]::Max(250, $script:groupDisks.ClientSize.Width - 24), 28)
|
||||
$selectorWidth = [Math]::Max(250, $script:groupDisks.ClientSize.Width - 24)
|
||||
$script:cmbDisk.Location = New-Object System.Drawing.Point(12, 38)
|
||||
$script:cmbDisk.Size = New-Object System.Drawing.Size($selectorWidth, 26)
|
||||
Set-DeployCenterPartitionProfileSelectorLayout `
|
||||
-Label $script:lblPartitionProfile `
|
||||
-ComboBox $script:cmbPartitionProfile `
|
||||
-Width $selectorWidth
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
@@ -730,6 +787,9 @@ function Set-ControlTheme {
|
||||
$Control.BackColor = $script:Theme.PanelAlt
|
||||
$Control.ForeColor = $script:Theme.Text
|
||||
}
|
||||
elseif ($Control -is [System.Windows.Forms.ComboBox]) {
|
||||
Set-DeployCenterComboBoxTheme -ComboBox $Control -Theme $script:Theme
|
||||
}
|
||||
elseif ($Control -is [System.Windows.Forms.TextBox]) {
|
||||
$Control.BackColor = $script:Theme.PanelAlt
|
||||
$Control.ForeColor = $script:Theme.Text
|
||||
@@ -1328,8 +1388,8 @@ function Show-WindowsSourcesDialog {
|
||||
$list.Location = New-Object System.Drawing.Point(16, 112)
|
||||
$list.Size = New-Object System.Drawing.Size([Math]::Max(300, $clientWidth - 32), [Math]::Max(120, $clientHeight - 205))
|
||||
$list.Anchor = 'Top,Bottom,Left,Right'
|
||||
$lblStatus.Location = New-Object System.Drawing.Point(16, ($clientHeight - 40))
|
||||
$lblStatus.Size = New-Object System.Drawing.Size([Math]::Max(300, $clientWidth - 32), 32)
|
||||
$lblStatus.Location = New-Object System.Drawing.Point(16, ($clientHeight - 52))
|
||||
$lblStatus.Size = New-Object System.Drawing.Size([Math]::Max(300, $clientWidth - 32), 24)
|
||||
$lblStatus.Anchor = 'Bottom,Left,Right'
|
||||
}
|
||||
$dlg.Add_Shown({
|
||||
@@ -1342,7 +1402,7 @@ function Show-WindowsSourcesDialog {
|
||||
|
||||
$btnEditions.Add_Click({
|
||||
if ($list.SelectedItems.Count -eq 0) {
|
||||
[System.Windows.Forms.MessageBox]::Show('Sélectionne d''abord une source dans la liste.', 'Éditions Windows', 'OK', 'Information') | Out-Null
|
||||
Show-DeployCenterMessage -Message 'Sélectionne d''abord une source dans la liste.' -Title 'Éditions Windows' -Icon Information -Owner $dlg -Theme $script:Theme -Font $script:FontRegular
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1567,7 +1627,7 @@ function Show-WindowsSourcesDialog {
|
||||
} catch {
|
||||
$lblStatus.Text = "Echec de l'analyse des editions de $selectedName."
|
||||
Write-Log "Erreur analyse editions $selectedPath : $($_.Exception.Message)" 'ERROR'
|
||||
[System.Windows.Forms.MessageBox]::Show($_.Exception.Message, 'Analyse des editions', 'OK', 'Warning') | Out-Null
|
||||
Show-DeployCenterMessage -Message $_.Exception.Message -Title 'Analyse des éditions' -Icon Warning -Owner $dlg -Theme $script:Theme -Font $script:FontRegular
|
||||
} finally {
|
||||
$dlg.Cursor = [System.Windows.Forms.Cursors]::Default
|
||||
$btnEditions.Enabled = $true
|
||||
@@ -1592,7 +1652,7 @@ function Show-WindowsSourcesDialog {
|
||||
} catch {
|
||||
$lblStatus.Text = 'Echec de la recherche. Consulte le message.'
|
||||
Write-Log "Erreur detection sources : $($_.Exception.Message)" 'ERROR'
|
||||
[System.Windows.Forms.MessageBox]::Show($_.Exception.Message, 'Detection des sources', 'OK', 'Warning') | Out-Null
|
||||
Show-DeployCenterMessage -Message $_.Exception.Message -Title 'Détection des sources' -Icon Warning -Owner $dlg -Theme $script:Theme -Font $script:FontRegular
|
||||
} finally {
|
||||
$dlg.Cursor = [System.Windows.Forms.Cursors]::Default
|
||||
$btnScan.Enabled = $true
|
||||
@@ -1643,7 +1703,7 @@ function Update-HardwareView {
|
||||
try {
|
||||
$script:cmbDisk.Items.Clear()
|
||||
foreach ($disk in $info.Disks) {
|
||||
$diskLabel = "Disque {0} - {1} - {2:N1} Go - {3} - {4}" -f $disk.Index, $disk.Model, $disk.SizeGB, $disk.Interface, $disk.Status
|
||||
$diskLabel = "Disque {0} - {1} - {2:N1} Go - {3} - {4}" -f $disk.Index, $disk.Model, $disk.SizeGB, $disk.BusType, $disk.Status
|
||||
$diskChoice = [pscustomobject]@{ Text = $diskLabel; Tag = [string]$disk.Index }
|
||||
[void]$script:cmbDisk.Items.Add($diskChoice)
|
||||
}
|
||||
@@ -1663,8 +1723,6 @@ function Update-HardwareView {
|
||||
$script:cmbDisk.EndUpdate()
|
||||
}
|
||||
|
||||
$json = $info | ConvertTo-Json -Depth 6
|
||||
Set-Content -LiteralPath $script:HardwareJson -Value $json -Encoding UTF8
|
||||
Write-DeployInventory -HardwareInfo $info
|
||||
|
||||
Write-Log "Inventaire materiel actualise." "SUCCESS"
|
||||
@@ -1680,12 +1738,7 @@ function Update-HardwareView {
|
||||
catch {
|
||||
Write-Log "Erreur inventaire : $($_.Exception.Message)" "ERROR"
|
||||
|
||||
[System.Windows.Forms.MessageBox]::Show(
|
||||
$_.Exception.Message,
|
||||
"Erreur DeployCenter",
|
||||
[System.Windows.Forms.MessageBoxButtons]::OK,
|
||||
[System.Windows.Forms.MessageBoxIcon]::Error
|
||||
) | Out-Null
|
||||
Show-DeployCenterMessage -Message $_.Exception.Message -Title 'Erreur DeployCenter' -Icon Error -Owner $script:form -Theme $script:Theme -Font $script:FontRegular
|
||||
}
|
||||
finally {
|
||||
$script:btnRefresh.Enabled = $true
|
||||
@@ -1714,7 +1767,7 @@ function Update-DeployCenterLayout {
|
||||
$script:groupPC.Location = New-Object System.Drawing.Point($m, 100)
|
||||
$script:groupPC.Size = New-Object System.Drawing.Size($contentWidth, 105)
|
||||
$script:groupDisks.Location = New-Object System.Drawing.Point($m, 220)
|
||||
$script:groupDisks.Size = New-Object System.Drawing.Size($contentWidth, 78)
|
||||
$script:groupDisks.Size = New-Object System.Drawing.Size($contentWidth, 116)
|
||||
Set-DiskSelectorWidth
|
||||
|
||||
# Le journal absorbe l'espace vertical restant au-dessus des actions et du pied de page.
|
||||
@@ -1765,6 +1818,15 @@ $script:cmbDisk.Add_SizeChanged({
|
||||
Set-DiskSelectorWidth
|
||||
})
|
||||
|
||||
$script:cmbPartitionProfile.Add_SelectedIndexChanged({
|
||||
$selectedIndex = $script:cmbPartitionProfile.SelectedIndex
|
||||
if ($selectedIndex -ge 0 -and $selectedIndex -lt $script:PartitionProfiles.Count) {
|
||||
$script:SelectedPartitionProfileIndex = $selectedIndex
|
||||
$script:SelectedPartitionProfile = $script:PartitionProfiles[$selectedIndex]
|
||||
Write-Log "Profil de partitionnement sélectionné : $($script:SelectedPartitionProfile.Name)" 'INFO'
|
||||
}
|
||||
})
|
||||
|
||||
$script:form.Add_SizeChanged({
|
||||
Update-DeployCenterLayout
|
||||
})
|
||||
|
||||
+9
-87
@@ -73,20 +73,22 @@ function Get-HardwareInfo {
|
||||
|
||||
# Inventaire des disques physiques
|
||||
try {
|
||||
$disks = Get-CimInstance `
|
||||
-ClassName Win32_DiskDrive `
|
||||
-ErrorAction Stop
|
||||
$disks = @(Get-Disk -ErrorAction Stop)
|
||||
|
||||
foreach ($disk in $disks) {
|
||||
$operationalStatus = @($disk.OperationalStatus | ForEach-Object { [string]$_ } | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
|
||||
$status = if ($operationalStatus.Count -gt 0) { $operationalStatus -join ', ' } else { 'Inconnu' }
|
||||
|
||||
$info.Disks += [PSCustomObject]@{
|
||||
Index = [int]$disk.Index
|
||||
Model = $disk.Model
|
||||
Index = [int]$disk.Number
|
||||
Model = [string]$disk.FriendlyName
|
||||
SizeBytes = [long]$disk.Size
|
||||
SizeGB = [math]::Round(
|
||||
([double]$disk.Size / 1GB), 1
|
||||
)
|
||||
InterfaceType = $disk.InterfaceType
|
||||
Status = $disk.Status
|
||||
BusType = [string]$disk.BusType
|
||||
Status = $status
|
||||
HealthStatus = [string]$disk.HealthStatus
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,83 +99,3 @@ function Get-HardwareInfo {
|
||||
# Retourner un objet exploitable par les autres modules
|
||||
[PSCustomObject]$info
|
||||
}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Execution du test
|
||||
# ============================================================
|
||||
|
||||
$LogDirectory = "X:\DeployLogs"
|
||||
$JsonPath = Join-Path $LogDirectory "hardware.json"
|
||||
$TextPath = Join-Path $LogDirectory "hardware.log"
|
||||
|
||||
try {
|
||||
New-Item -ItemType Directory `
|
||||
-Path $LogDirectory `
|
||||
-Force `
|
||||
-ErrorAction Stop | Out-Null
|
||||
}
|
||||
catch {
|
||||
throw "Impossible de creer le repertoire de logs : $($_.Exception.Message)"
|
||||
}
|
||||
|
||||
$result = Get-HardwareInfo
|
||||
|
||||
# Export JSON en UTF-8 avec BOM sous Windows PowerShell 5.1
|
||||
try {
|
||||
$json = $result | ConvertTo-Json -Depth 5
|
||||
|
||||
Set-Content `
|
||||
-Path $JsonPath `
|
||||
-Value $json `
|
||||
-Encoding UTF8 `
|
||||
-ErrorAction Stop
|
||||
}
|
||||
catch {
|
||||
throw "Impossible d'enregistrer le JSON : $($_.Exception.Message)"
|
||||
}
|
||||
|
||||
# Construire un journal texte sans utiliser Write-Host
|
||||
$lines = @(
|
||||
"=== DeployCenter - Inventaire materiel ==="
|
||||
"Date : $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
||||
"Fabricant : $($result.Manufacturer)"
|
||||
"Modele : $($result.Model)"
|
||||
"Numero serie : $($result.SerialNumber)"
|
||||
"Firmware : $($result.Firmware)"
|
||||
"Architecture : $($result.Architecture)"
|
||||
"WinPE : $($result.WinPE)"
|
||||
""
|
||||
"=== Disques detectes ==="
|
||||
)
|
||||
|
||||
foreach ($disk in $result.Disks) {
|
||||
$lines += (
|
||||
"Disque {0} : {1} - {2} Go - {3} - {4}" -f
|
||||
$disk.Index,
|
||||
$disk.Model,
|
||||
$disk.SizeGB,
|
||||
$disk.InterfaceType,
|
||||
$disk.Status
|
||||
)
|
||||
}
|
||||
|
||||
if ($result.Errors.Count -gt 0) {
|
||||
$lines += ""
|
||||
$lines += "=== Erreurs ==="
|
||||
|
||||
foreach ($message in $result.Errors) {
|
||||
$lines += $message
|
||||
}
|
||||
}
|
||||
|
||||
$utf8 = New-Object System.Text.UTF8Encoding($false)
|
||||
|
||||
[System.IO.File]::WriteAllLines(
|
||||
$TextPath,
|
||||
[string[]]$lines,
|
||||
$utf8
|
||||
)
|
||||
|
||||
# Renvoyer l'objet comme sortie principale du script
|
||||
$result
|
||||
+25
-6
@@ -9,17 +9,36 @@ function Get-DeployNetworkIPv4 {
|
||||
# APIPA et adresses IPv4 non routables couramment inutiles en WinPE.
|
||||
$candidates = @()
|
||||
try {
|
||||
foreach ($cfg in (Get-CimInstance Win32_NetworkAdapterConfiguration -Filter 'IPEnabled=True' -ErrorAction Stop)) {
|
||||
$hasGateway = @($cfg.DefaultIPGateway | Where-Object { $_ -match '^\d{1,3}(\.\d{1,3}){3}$' }).Count -gt 0
|
||||
foreach ($address in @($cfg.IPAddress | Where-Object { $_ -match '^\d{1,3}(\.\d{1,3}){3}$' })) {
|
||||
if ($address -eq '127.0.0.1' -or $address -like '169.254.*' -or $address -eq '0.0.0.0') { continue }
|
||||
$candidates += [pscustomobject]@{ Address = $address; HasGateway = $hasGateway; Index = [int]$cfg.Index }
|
||||
foreach ($interface in [System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces()) {
|
||||
if ($interface.NetworkInterfaceType -eq [System.Net.NetworkInformation.NetworkInterfaceType]::Loopback) { continue }
|
||||
|
||||
$properties = $interface.GetIPProperties()
|
||||
$ipv4Properties = $properties.GetIPv4Properties()
|
||||
if ($null -eq $ipv4Properties) { continue }
|
||||
|
||||
$hasGateway = @(
|
||||
$properties.GatewayAddresses | Where-Object {
|
||||
$_.Address.AddressFamily -eq [System.Net.Sockets.AddressFamily]::InterNetwork -and
|
||||
$_.Address.ToString() -ne '0.0.0.0'
|
||||
}
|
||||
).Count -gt 0
|
||||
|
||||
foreach ($unicast in $properties.UnicastAddresses) {
|
||||
$address = $unicast.Address
|
||||
if ($address.AddressFamily -ne [System.Net.Sockets.AddressFamily]::InterNetwork) { continue }
|
||||
$addressText = $address.ToString()
|
||||
if ($addressText -eq '127.0.0.1' -or $addressText -like '169.254.*' -or $addressText -eq '0.0.0.0') { continue }
|
||||
$candidates += [pscustomobject]@{
|
||||
Address = $addressText
|
||||
HasGateway = $hasGateway
|
||||
Index = [int]$ipv4Properties.Index
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
# La détection réseau ne doit pas empêcher le démarrage de DeployCenter.
|
||||
if (Get-Command Write-Log -ErrorAction SilentlyContinue) {
|
||||
Write-Log "Détection réseau WMI : $($_.Exception.Message)" 'WARNING'
|
||||
Write-Log "Détection réseau : $($_.Exception.Message)" 'WARNING'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
# DeployCenter - Chargement et validation des profils de partitionnement
|
||||
# Les profils PSD1 sont des fichiers de données ; ils ne contiennent aucun code exécuté.
|
||||
|
||||
function Get-DeployCenterPartitionProfileNames {
|
||||
[CmdletBinding()]
|
||||
param([Parameter(Mandatory=$true)][string]$ProfilesRoot)
|
||||
|
||||
if (-not (Test-Path -LiteralPath $ProfilesRoot -PathType Container)) { return @() }
|
||||
$names = @()
|
||||
foreach ($file in (Get-ChildItem -LiteralPath $ProfilesRoot -Filter '*.psd1' -File -ErrorAction SilentlyContinue)) {
|
||||
if ($file.BaseName -match '^[A-Za-z0-9_-]+$') { $names += $file.BaseName }
|
||||
}
|
||||
return @($names | Sort-Object -Unique)
|
||||
}
|
||||
|
||||
function Import-DeployCenterPartitionProfile {
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$ProfilesRoot,
|
||||
[Parameter(Mandatory=$true)][string]$ProfileName
|
||||
)
|
||||
|
||||
if ($ProfileName -notmatch '^[A-Za-z0-9_-]+$') { throw "Nom de profil invalide : $ProfileName" }
|
||||
$path = Join-Path $ProfilesRoot ($ProfileName + '.psd1')
|
||||
if (-not (Test-Path -LiteralPath $path -PathType Leaf)) { throw "Profil introuvable : $ProfileName" }
|
||||
|
||||
$profile = Import-PowerShellDataFile -LiteralPath $path
|
||||
foreach ($key in @('Id','Name','Description','Firmware','PartitionStyle','Partitions')) {
|
||||
if (-not $profile.ContainsKey($key)) { throw "Le profil '$ProfileName' ne contient pas la clé '$key'." }
|
||||
}
|
||||
if ([string]$profile.Id -ne $ProfileName) { throw "L'identifiant du profil '$ProfileName' ne correspond pas au nom du fichier." }
|
||||
if (@($profile.Partitions).Count -lt 2) { throw "Le profil '$ProfileName' doit définir au moins deux partitions." }
|
||||
if (@($profile.Partitions | Where-Object { [string]$_.Role -eq 'Windows' }).Count -ne 1) {
|
||||
throw "Le profil '$ProfileName' doit définir exactement une partition Windows."
|
||||
}
|
||||
$userInputPartitions = @($profile.Partitions | Where-Object { [string]$_.Size.Policy -eq 'UserInputGB' })
|
||||
$remainderPartitions = @($profile.Partitions | Where-Object { [string]$_.Size.Policy -eq 'RemainderAfterInputs' })
|
||||
$remainingPartitions = @($profile.Partitions | Where-Object { [string]$_.Size.Policy -eq 'Remaining' })
|
||||
if ($userInputPartitions.Count -gt 0) {
|
||||
if ($remainderPartitions.Count -ne 1 -or $remainingPartitions.Count -gt 0) {
|
||||
throw "Le profil '$ProfileName' doit associer les saisies utilisateur à une partition de reste unique."
|
||||
}
|
||||
} elseif ($remainingPartitions.Count -ne 1 -or [string]$profile.Partitions[-1].Size.Policy -ne 'Remaining') {
|
||||
throw "Le profil '$ProfileName' doit placer une unique partition utilisant l'espace restant en dernière position."
|
||||
}
|
||||
foreach ($partition in $profile.Partitions) {
|
||||
foreach ($key in @('Name','Role','FileSystem','Size')) {
|
||||
if (-not $partition.ContainsKey($key)) { throw "Une partition du profil '$ProfileName' ne contient pas la clé '$key'." }
|
||||
}
|
||||
if (-not $partition.Size.ContainsKey('Policy')) { throw "La taille d'une partition du profil '$ProfileName' ne définit pas Policy." }
|
||||
switch ([string]$partition.Size.Policy) {
|
||||
'FixedMB' {
|
||||
if ([int]$partition.Size.Value -le 0) { throw "Une taille fixe du profil '$ProfileName' doit être supérieure à zéro." }
|
||||
}
|
||||
'ImageSizePlusFreeSpace' {
|
||||
if ([int]$partition.Size.FreeSpaceMB -lt 250) { throw "La marge libre WinRE du profil '$ProfileName' doit être d'au moins 250 Mo." }
|
||||
if ([int]$partition.Size.PreviewMB -le 0) { throw "Le profil '$ProfileName' doit définir une réserve PreviewMB pour estimer la capacité disponible." }
|
||||
}
|
||||
'UserInputGB' {
|
||||
if ([int]$partition.Size.MinimumGB -le 0 -or [int]$partition.Size.DefaultPercent -le 0 -or [int]$partition.Size.DefaultPercent -ge 100) {
|
||||
throw "La saisie de taille utilisateur du profil '$ProfileName' doit définir MinimumGB et un DefaultPercent entre 1 et 99."
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace([string]$partition.Size.Label)) { throw "La saisie de taille utilisateur du profil '$ProfileName' doit définir Label." }
|
||||
}
|
||||
'RemainderAfterInputs' {
|
||||
if ([double]$partition.Size.MinimumGB -lt 0 -or [string]::IsNullOrWhiteSpace([string]$partition.Size.Label)) {
|
||||
throw "La partition de reste du profil '$ProfileName' doit définir un MinimumGB non négatif et un Label."
|
||||
}
|
||||
}
|
||||
'Remaining' { }
|
||||
default { throw "Politique de taille inconnue dans le profil '$ProfileName' : $($partition.Size.Policy)" }
|
||||
}
|
||||
}
|
||||
|
||||
return $profile
|
||||
}
|
||||
|
||||
function Get-DeployCenterPartitionSizingCapacity {
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][System.Collections.IDictionary]$Profile,
|
||||
[Parameter(Mandatory=$true)][long]$DiskSizeBytes
|
||||
)
|
||||
|
||||
$reservedMB = 0.0
|
||||
foreach ($partition in $Profile.Partitions) {
|
||||
switch ([string]$partition.Size.Policy) {
|
||||
'FixedMB' { $reservedMB += [double]$partition.Size.Value }
|
||||
default {
|
||||
if ($partition.Size.ContainsKey('PreviewMB')) { $reservedMB += [double]$partition.Size.PreviewMB }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$capacityBytes = $DiskSizeBytes - [long][math]::Ceiling($reservedMB * 1MB)
|
||||
if ($capacityBytes -le 0) { throw "Le disque est trop petit pour les réserves du profil '$($Profile.Name)'." }
|
||||
return [pscustomobject]@{
|
||||
UsableBytes = [long]$capacityBytes
|
||||
UsableGB = [math]::Round(($capacityBytes / 1GB), 1)
|
||||
ReservedMB = [math]::Ceiling($reservedMB)
|
||||
}
|
||||
}
|
||||
|
||||
Export-ModuleMember -Function Get-DeployCenterPartitionProfileNames, Import-DeployCenterPartitionProfile, Get-DeployCenterPartitionSizingCapacity
|
||||
+142
-1
@@ -19,4 +19,145 @@
|
||||
}
|
||||
}
|
||||
|
||||
Export-ModuleMember -Function Set-DeployCenterButtonStyle
|
||||
function New-DeployCenterComboBox {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$Name,
|
||||
[Parameter(Mandatory=$true)][System.Collections.IDictionary]$Theme,
|
||||
[Parameter(Mandatory=$true)][System.Drawing.Font]$Font,
|
||||
[Parameter(Mandatory=$true)][string[]]$Items
|
||||
)
|
||||
|
||||
$comboBox = New-Object System.Windows.Forms.ComboBox
|
||||
$comboBox.Name = $Name
|
||||
$comboBox.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList
|
||||
$comboBox.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat
|
||||
$comboBox.BackColor = $Theme.PanelAlt
|
||||
$comboBox.ForeColor = $Theme.Text
|
||||
$comboBox.Font = $Font
|
||||
$comboBox.IntegralHeight = $false
|
||||
$comboBox.MaxDropDownItems = 12
|
||||
foreach ($item in $Items) { [void]$comboBox.Items.Add($item) }
|
||||
return $comboBox
|
||||
}
|
||||
|
||||
function Set-DeployCenterComboBoxTheme {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][System.Windows.Forms.ComboBox]$ComboBox,
|
||||
[Parameter(Mandatory=$true)][System.Collections.IDictionary]$Theme
|
||||
)
|
||||
$ComboBox.BackColor = $Theme.PanelAlt
|
||||
$ComboBox.ForeColor = $Theme.Text
|
||||
}
|
||||
|
||||
function New-DeployCenterPartitionProfileSelector {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][System.Windows.Forms.GroupBox]$Parent,
|
||||
[Parameter(Mandatory=$true)][string[]]$ProfileNames,
|
||||
[Parameter(Mandatory=$true)][System.Collections.IDictionary]$Theme,
|
||||
[Parameter(Mandatory=$true)][System.Drawing.Font]$Font
|
||||
)
|
||||
|
||||
$label = New-Object System.Windows.Forms.Label
|
||||
$label.Text = 'Profil de partitionnement'
|
||||
$label.Size = New-Object System.Drawing.Size(240, 17)
|
||||
$label.ForeColor = $Theme.Text
|
||||
$label.BackColor = [System.Drawing.Color]::Transparent
|
||||
$label.Font = $Font
|
||||
|
||||
$comboBox = New-DeployCenterComboBox -Name 'cmbPartitionProfile' -Theme $Theme -Font $Font -Items $ProfileNames
|
||||
$Parent.Controls.Add($label)
|
||||
$Parent.Controls.Add($comboBox)
|
||||
Set-DeployCenterPartitionProfileSelectorLayout -Label $label -ComboBox $comboBox -Width ($Parent.ClientSize.Width - 24)
|
||||
|
||||
return [pscustomobject]@{ Label = $label; ComboBox = $comboBox }
|
||||
}
|
||||
|
||||
function Set-DeployCenterPartitionProfileSelectorLayout {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][System.Windows.Forms.Label]$Label,
|
||||
[Parameter(Mandatory=$true)][System.Windows.Forms.ComboBox]$ComboBox,
|
||||
[Parameter(Mandatory=$true)][int]$Width
|
||||
)
|
||||
$Label.Location = New-Object System.Drawing.Point(12, 66)
|
||||
$ComboBox.Location = New-Object System.Drawing.Point(12, 84)
|
||||
$ComboBox.Size = New-Object System.Drawing.Size([Math]::Max(250, $Width), 26)
|
||||
}
|
||||
|
||||
function Show-DeployCenterMessage {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$Message,
|
||||
[Parameter(Mandatory=$true)][string]$Title,
|
||||
[ValidateSet('Information','Warning','Error')][string]$Icon = 'Information',
|
||||
[System.Windows.Forms.Form]$Owner = $null,
|
||||
[Parameter(Mandatory=$true)][System.Collections.IDictionary]$Theme,
|
||||
[Parameter(Mandatory=$true)][System.Drawing.Font]$Font
|
||||
)
|
||||
|
||||
$messageForm = New-Object System.Windows.Forms.Form
|
||||
$messageForm.Text = $Title
|
||||
$messageForm.StartPosition = if ($Owner) { 'CenterParent' } else { 'CenterScreen' }
|
||||
$messageForm.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedDialog
|
||||
$messageForm.ShowInTaskbar = $false
|
||||
$messageForm.MinimizeBox = $false
|
||||
$messageForm.MaximizeBox = $false
|
||||
$messageForm.BackColor = $Theme.Background
|
||||
$messageForm.ForeColor = $Theme.Text
|
||||
$messageForm.Font = $Font
|
||||
|
||||
$messageWidth = 390
|
||||
$textSize = [System.Windows.Forms.TextRenderer]::MeasureText(
|
||||
$Message,
|
||||
$Font,
|
||||
(New-Object System.Drawing.Size($messageWidth, 0)),
|
||||
[System.Windows.Forms.TextFormatFlags]::WordBreak
|
||||
)
|
||||
$messageHeight = [Math]::Max(42, $textSize.Height + 8)
|
||||
$messageForm.ClientSize = New-Object System.Drawing.Size(470, ($messageHeight + 94))
|
||||
|
||||
$iconLabel = New-Object System.Windows.Forms.Label
|
||||
$iconLabel.Location = New-Object System.Drawing.Point(18, 24)
|
||||
$iconLabel.Size = New-Object System.Drawing.Size(34, 34)
|
||||
$iconLabel.Text = if ($Icon -eq 'Information') { 'i' } else { '!' }
|
||||
$iconLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
|
||||
$iconLabel.Font = New-Object System.Drawing.Font('Segoe UI', [single]16, [System.Drawing.FontStyle]::Bold)
|
||||
$iconLabel.ForeColor = if ($Icon -eq 'Error') { $Theme.Danger } else { $Theme.Accent }
|
||||
$iconLabel.BackColor = [System.Drawing.Color]::Transparent
|
||||
$messageForm.Controls.Add($iconLabel)
|
||||
|
||||
$messageLabel = New-Object System.Windows.Forms.Label
|
||||
$messageLabel.Location = New-Object System.Drawing.Point(64, 20)
|
||||
$messageLabel.Size = New-Object System.Drawing.Size($messageWidth, $messageHeight)
|
||||
$messageLabel.Text = $Message
|
||||
$messageLabel.ForeColor = $Theme.Text
|
||||
$messageLabel.BackColor = [System.Drawing.Color]::Transparent
|
||||
$messageLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleLeft
|
||||
$messageLabel.Font = $Font
|
||||
$messageForm.Controls.Add($messageLabel)
|
||||
|
||||
$buttonPanel = New-Object System.Windows.Forms.Panel
|
||||
$buttonPanel.Dock = [System.Windows.Forms.DockStyle]::Bottom
|
||||
$buttonPanel.Height = 58
|
||||
$buttonPanel.BackColor = $Theme.PanelAlt
|
||||
$messageForm.Controls.Add($buttonPanel)
|
||||
|
||||
$okButton = New-Object System.Windows.Forms.Button
|
||||
$okButton.Text = 'OK'
|
||||
$okButton.Location = New-Object System.Drawing.Point(362, 10)
|
||||
$okButton.Size = New-Object System.Drawing.Size(92, 36)
|
||||
$okButton.Font = $Font
|
||||
$okButton.Cursor = [System.Windows.Forms.Cursors]::Hand
|
||||
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
|
||||
Set-DeployCenterButtonStyle -Button $okButton -Theme $Theme -Role 'PrimaryButton'
|
||||
$buttonPanel.Controls.Add($okButton)
|
||||
$messageForm.AcceptButton = $okButton
|
||||
$messageForm.CancelButton = $okButton
|
||||
|
||||
if ($Owner) {
|
||||
[void]$messageForm.ShowDialog($Owner)
|
||||
} else {
|
||||
[void]$messageForm.ShowDialog()
|
||||
}
|
||||
$messageForm.Dispose()
|
||||
}
|
||||
|
||||
Export-ModuleMember -Function Set-DeployCenterButtonStyle, New-DeployCenterComboBox, Set-DeployCenterComboBoxTheme, New-DeployCenterPartitionProfileSelector, Set-DeployCenterPartitionProfileSelectorLayout, Show-DeployCenterMessage
|
||||
+18
-6
@@ -8,7 +8,6 @@ function Start-DeployCenterVnc {
|
||||
$passwordTool = Join-Path $sourceVnc 'createpassword64.exe'
|
||||
$sourceIni = Join-Path $sourceVnc 'ultravnc.ini'
|
||||
|
||||
$script:DeployIPv4 = Get-DeployNetworkIPv4
|
||||
if ([string]::IsNullOrWhiteSpace($script:DeployIPv4)) {
|
||||
Write-Log 'Aucune adresse IPv4 de déploiement détectée.' 'WARNING'
|
||||
}
|
||||
@@ -29,25 +28,36 @@ function Start-DeployCenterVnc {
|
||||
return
|
||||
}
|
||||
|
||||
$vncStage = 'préparation du dossier temporaire'
|
||||
try {
|
||||
if (Test-Path -LiteralPath $script:VncDirectory) {
|
||||
Remove-Item -LiteralPath $script:VncDirectory -Recurse -Force -ErrorAction Stop
|
||||
}
|
||||
New-Item -Path $script:VncDirectory -ItemType Directory -Force | Out-Null
|
||||
$vncStage = "copie des fichiers depuis $sourceVnc vers $script:VncDirectory"
|
||||
Copy-Item -Path (Join-Path $sourceVnc '*') -Destination $script:VncDirectory -Recurse -Force
|
||||
# WinPE ne permet pas toujours d'ajouter des règles de pare-feu.
|
||||
# La désactivation globale n'est effectuée que lorsque VNC est demandé.
|
||||
$vncStage = 'désactivation du pare-feu WinPE'
|
||||
$wpeutil = Join-Path $env:WINDIR 'System32\wpeutil.exe'
|
||||
if (-not (Test-Path -LiteralPath $wpeutil -PathType Leaf)) {
|
||||
$wpeutil = 'wpeutil.exe'
|
||||
}
|
||||
& $wpeutil DisableFirewall
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "wpeutil DisableFirewall a renvoyé le code $LASTEXITCODE."
|
||||
$wpeutilOutput = @(& $wpeutil DisableFirewall 2>&1)
|
||||
$wpeutilExitCode = $LASTEXITCODE
|
||||
foreach ($outputLine in $wpeutilOutput) {
|
||||
$outputText = [string]$outputLine
|
||||
if (-not [string]::IsNullOrWhiteSpace($outputText)) {
|
||||
Write-Log "wpeutil DisableFirewall : $outputText" 'INFO'
|
||||
}
|
||||
}
|
||||
Write-Log 'Pare-feu WinPE désactivé à la demande de -Vnc.' 'WARNING'
|
||||
if ($wpeutilExitCode -ne 0) {
|
||||
throw "wpeutil DisableFirewall a renvoyé le code $wpeutilExitCode."
|
||||
}
|
||||
Write-Log "Pare-feu WinPE désactivé à la demande de -Vnc (code wpeutil : $wpeutilExitCode)." 'WARNING'
|
||||
|
||||
# Force le mode portable : l'INI actif est celui placé à côté de winvnc.exe.
|
||||
$vncStage = 'activation du mode portable UltraVNC'
|
||||
$portableFlag = Join-Path $script:VncDirectory 'ultravnc.portable'
|
||||
Set-Content -LiteralPath $portableFlag -Value '' -Encoding ASCII
|
||||
|
||||
@@ -64,6 +74,7 @@ function Start-DeployCenterVnc {
|
||||
}
|
||||
|
||||
# createpassword64 encode le mot de passe choisi dans le champ passwd d'ultravnc.ini.
|
||||
$vncStage = 'génération du mot de passe UltraVNC'
|
||||
$tool = Join-Path $script:VncDirectory 'createpassword64.exe'
|
||||
$script:VncProcess = Start-Process -FilePath $tool -ArgumentList @($script:VncPassword) `
|
||||
-WorkingDirectory $script:VncDirectory -Wait -PassThru -WindowStyle Hidden
|
||||
@@ -78,6 +89,7 @@ function Start-DeployCenterVnc {
|
||||
}
|
||||
|
||||
$server = Join-Path $script:VncDirectory 'winvnc.exe'
|
||||
$vncStage = 'démarrage du serveur UltraVNC'
|
||||
$script:VncProcess = Start-Process -FilePath $server -ArgumentList @('-run') `
|
||||
-WorkingDirectory $script:VncDirectory -PassThru -WindowStyle Hidden
|
||||
Start-Sleep -Milliseconds 800
|
||||
@@ -87,7 +99,7 @@ function Start-DeployCenterVnc {
|
||||
$script:VncStarted = $true
|
||||
Write-Log "UltraVNC démarré. IP : $($script:DeployIPv4) ; mot de passe $passwordSource." 'SUCCESS'
|
||||
} catch {
|
||||
Write-Log "Échec du démarrage UltraVNC : $($_.Exception.Message)" 'ERROR'
|
||||
Write-Log "Échec du démarrage UltraVNC à l'étape '$vncStage' : $($_.Exception.Message)" 'ERROR'
|
||||
$script:VncStarted = $false
|
||||
$script:VncPassword = $null
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
@{
|
||||
Id = 'UEFI-GPT-WinRE-before-C'
|
||||
Name = 'UEFI / GPT — WinRE avant C:'
|
||||
Description = "Crée EFI, MSR et WinRE avant la partition Windows qui occupe l’espace restant."
|
||||
Default = $true
|
||||
Firmware = 'UEFI'
|
||||
PartitionStyle = 'GPT'
|
||||
Partitions = @(
|
||||
@{
|
||||
Name = 'EFI'
|
||||
Role = 'System'
|
||||
FileSystem = 'FAT32'
|
||||
GptTypeId = 'C12A7328-F81F-11D2-BA4B-00A0C93EC93B'
|
||||
Size = @{ Policy = 'FixedMB'; Value = 300 }
|
||||
}
|
||||
@{
|
||||
Name = 'MSR'
|
||||
Role = 'Reserved'
|
||||
FileSystem = $null
|
||||
GptTypeId = 'E3C9E316-0B5C-4DB8-817D-F92DF00215AE'
|
||||
Size = @{ Policy = 'FixedMB'; Value = 16 }
|
||||
}
|
||||
@{
|
||||
Name = 'WinRE'
|
||||
Role = 'Recovery'
|
||||
FileSystem = 'NTFS'
|
||||
GptTypeId = 'DE94BBA4-06D1-4D40-A16A-BFD50179D6AC'
|
||||
GptAttributes = '0x8000000000000001'
|
||||
Size = @{ Policy = 'ImageSizePlusFreeSpace'; FreeSpaceMB = 250; PreviewMB = 1024 }
|
||||
}
|
||||
@{
|
||||
Name = 'Windows'
|
||||
Role = 'Windows'
|
||||
FileSystem = 'NTFS'
|
||||
GptTypeId = 'EBD0A0A2-B9E5-4433-87C0-68B6B72699C7'
|
||||
DriveLetterAfterReboot = 'C'
|
||||
Size = @{ Policy = 'Remaining' }
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -92,3 +92,28 @@ La gestion d'UltraVNC est isolée dans `Modules/VNC.psm1`. Le fichier est charg
|
||||
|
||||
- `Modules/Network.psm1` : détection de l’adresse IPv4 de déploiement, utilisée par le pied de page et le nom du journal.
|
||||
- `Modules/Logging.psm1` : initialisation et écriture des journaux. L’adresse IPv4 détectée lui est transmise par le script principal.
|
||||
- `Modules/Partitioning.psm1` : découverte et validation des profils de partitionnement déclarés dans `Partitioning/Profiles/*.psd1`.
|
||||
|
||||
## Profils de partitionnement
|
||||
|
||||
Les fichiers PSD1 de `Partitioning/Profiles` décrivent les schémas de partitionnement comme des données, sans exécuter de code contenu dans les profils. Le profil actuellement disponible est « UEFI / GPT — WinRE avant C: » : EFI (300 Mo), MSR (16 Mo), WinRE (taille de `winre.wim` plus 250 Mo libres), puis Windows sur l’espace restant. Il est marqué comme profil par défaut. La sélection est visible dans l’interface ; le calcul effectif de la taille WinRE et l’exécution du partitionnement ne sont pas encore implémentés.
|
||||
|
||||
|
||||
## Historique des changements
|
||||
|
||||
### 2026-10-15
|
||||
|
||||
- Les anciens exports de `HardwareInfo.ps1` ont d’abord été déplacés sous `%TEMP%\DeployCenter`, puis retirés au profit du seul inventaire consolidé décrit ci-dessous.
|
||||
- L’affichage des disques a d’abord utilisé `InterfaceType`, puis a été corrigé pour afficher `BusType` obtenu par `Get-Disk`.
|
||||
- Le module VNC réutilise l’adresse IPv4 détectée au démarrage ; la détection réseau n’est plus relancée lors du démarrage de VNC.
|
||||
- Les messages d’information et d’erreur utilisent maintenant `Show-DeployCenterMessage` dans `Modules/UI.psm1`, avec la palette active, au lieu des boîtes de dialogue natives de Windows.
|
||||
- Les erreurs de démarrage VNC indiquent maintenant l’étape concernée pour distinguer les échecs de nettoyage, de copie, de pare-feu et de lancement.
|
||||
- La sortie de `wpeutil DisableFirewall` et son code de retour sont consignés dans le journal DeployCenter au lieu d’apparaître dans la console PowerShell.
|
||||
- Le libellé de statut de la fenêtre Sources Windows est remonté et sa hauteur réduite pour mieux le séparer du pied de page.
|
||||
- L’inventaire matériel, l’adresse IP et les informations VNC sont réunis dans `%TEMP%\DeployCenter\DeployCenter_Inventory.json`. Les exports distincts `HardwareInfo.json`, `hardware.json` et `hardware.log` ne sont plus générés.
|
||||
- Les anciens fichiers temporaires peuvent rester jusqu’au redémarrage de WinPE, qui vide `%TEMP%`.
|
||||
- La collecte complète des disques utilise maintenant `Get-Disk` : numéro, nom, taille, type de bus, état opérationnel et état de santé. `Win32_DiskDrive` n’est plus utilisé pour l’inventaire des disques.
|
||||
- La détection IPv4 de `Modules/Network.psm1` utilise les API .NET `System.Net.NetworkInformation` au lieu de `Get-CimInstance Win32_NetworkAdapterConfiguration` ; la priorité aux interfaces avec passerelle et les exclusions d’adresses restent en place.
|
||||
- Ajout du chargement et de la validation de profils de partitionnement PSD1, ainsi que d’un sélecteur dans l’interface. Le profil UEFI/GPT place EFI, MSR et WinRE avant Windows, qui reçoit l’espace restant ; aucun script DiskPart n’est exécuté à cette étape.
|
||||
- Ajout du BOM UTF-8 aux nouveaux fichiers PowerShell et PSD1 pour préserver les caractères accentués lors de leur lecture par Windows PowerShell 5.1.
|
||||
- Correction de l’apostrophe dans la description du profil UEFI/GPT, qui empêchait le chargement du fichier PSD1.
|
||||
Reference in new issue
Block a user