Public/Remove-HDTBootImageComponent.ps1
|
function Remove-HDTBootImageComponent { <# .SYNOPSIS Stops a WinPE optional component being applied to the boot image, leaving every other line of workspace.yaml byte-identical. .DESCRIPTION The command an administrator types to drop a WinPE optional component, and the one anything with a Remove button has to run. REMOVING THE LAST ONE WRITES AN EMPTY LIST, NOT NOTHING. An absent optionalComponents key means "the administrator did not say" and takes three defaults; an explicit empty list means "the required six and nothing else". Deleting the key would therefore bring back the very components that had just been removed, so the key stays and becomes []. A COMPONENT THAT IS NOT THERE IS AN ERROR, and that includes one that was only ever there by default: removing an unstated default writes the remaining defaults out, which is the only way to say "these two and not the third". THE REQUIRED SIX CANNOT BE REMOVED, because they are not in this list to begin with. WinPE-WMI, WinPE-NetFx, WinPE-Scripting, WinPE-PowerShell, WinPE-StorageWMI and WinPE-DismCmdlets are applied to every HDT boot image; the engine rests on PowerShell and DISM inside WinPE, so an image without them is not one this toolkit can deploy from. IT RETURNS LINES AND WRITES NOTHING. Save-HDTWorkspaceDocument is what touches the share. .PARAMETER Line The document, already split into lines. .PARAMETER Name The components to remove. .INPUTS None. This command does not accept pipeline input. .OUTPUTS System.String[] - the document with the components removed. .EXAMPLE Remove-HDTBootImageComponent -Line $line -Name 'WinPE-WDS-Tools' .LINK Add-HDTBootImageComponent .LINK Get-HDTAdkComponent #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] [OutputType([string[]])] param( [Parameter(Mandatory = $true, Position = 0)] [AllowEmptyCollection()] [AllowEmptyString()] [string[]] $Line, [Parameter(Mandatory = $true, Position = 1)] [ValidateNotNullOrEmpty()] [string[]] $Name ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' $workspace = ConvertFrom-HDTWorkspaceLine -Line $Line $declared = New-Object -TypeName System.Collections.ArrayList foreach ($current in @($workspace.BootImage.OptionalComponent)) { [void] $declared.Add([string] $current) } $going = New-Object -TypeName System.Collections.ArrayList foreach ($current in @($Name)) { $at = -1 for ($i = 0; $i -lt $declared.Count; $i++) { if ([string] $declared[$i] -eq $current) { $at = $i; break } if (([string] $declared[$i]).ToLowerInvariant() -eq $current.ToLowerInvariant()) { $at = $i; break } } if ($at -lt 0) { $PSCmdlet.ThrowTerminatingError((New-HDTErrorRecord -TargetObject $current -Category ObjectNotFound ` -Message ("'{0}' is not a component this boot image applies. It carries {1}, plus the six every HDT image applies whatever the document says." -f $current, (@($declared) -join ', ')))) } if ($going -contains ([string] $declared[$at])) { $PSCmdlet.ThrowTerminatingError((New-HDTErrorRecord -TargetObject $current ` -Message ("'{0}' was named twice in one removal." -f $current))) } [void] $going.Add([string] $declared[$at]) } if (-not $PSCmdlet.ShouldProcess((@($Name) -join ', '), 'Remove from the boot image components')) { return [string[]] @($Line) } $result = [string[]] @($Line) $block = Get-HDTWorkspaceKey -Line $result -Path @('bootImage', 'optionalComponents') if ($null -eq $block) { # THE DEFAULTS, MINUS THE ONES GOING, WRITTEN OUT. There is nothing in the # file to splice, and deleting from an unstated list has to say what is # left or it says nothing at all. $remaining = @($declared | Where-Object { $going -notcontains [string] $_ }) $written = New-Object -TypeName System.Collections.ArrayList if (@($remaining).Count -eq 0) { # An empty list is written as one rather than as a key with nothing # under it, which the engine reads as a null. [void] $written.Add('optionalComponents: []') } else { [void] $written.Add('optionalComponents:') foreach ($current in @($remaining)) { [void] $written.Add(' - {0}' -f (ConvertTo-HDTRuleScalarText -Value ([string] $current))) } } $result = [string[]] @(Set-HDTWorkspaceKey -Line $result -Path @('bootImage', 'optionalComponents') ` -Text ([string[]] @($written))) } else { # Highest position first, so removing one does not move the next. $position = New-Object -TypeName System.Collections.ArrayList foreach ($current in @($going)) { [void] $position.Add([int] ([array]::IndexOf([string[]] @($declared), [string] $current))) } foreach ($at in @(@($position) | Sort-Object -Descending)) { $result = [string[]] @(Remove-HDTWorkspaceItem -Line $result ` -Path @('bootImage', 'optionalComponents') -Position ([int] $at) ` -EmptyText ([string[]] @('optionalComponents: []'))) } } try { [void] (ConvertFrom-HDTWorkspaceLine -Line $result) } catch { $PSCmdlet.ThrowTerminatingError($_) } return [string[]] $result } |