private/Select-OSDeployCoreCacheWindowsRE.ps1

#Requires -PSEdition Core

function Select-OSDeployCoreCacheWindowsRE {
    <#
    .SYNOPSIS
        Selects an imported Windows Recovery Environment image
 
    .DESCRIPTION
        Gets imported Windows Recovery Environment images, optionally limits results to a
        Windows build major, and returns the only result
        automatically when exactly one is available. Multiple results are displayed in
        a native console table that supports Up and Down arrow navigation, Enter to select,
        and Escape to cancel.
 
        An interactive, nonredirected console is required only when multiple results must
        be displayed. The function writes a warning and returns no object when no matching
        images exist or interactive selection cannot be displayed.
 
    .PARAMETER Architecture
        Limits results to amd64 or arm64 before automatic or interactive selection.
 
    .PARAMETER BuildMajor
        Limits results to Windows build major 26200 or 26300 before automatic or
        interactive selection.
 
    .EXAMPLE
        PS> Select-OSDeployCoreCacheWindowsRE -Architecture amd64 -BuildMajor 26200
 
        Returns or displays imported amd64 images matching Windows build 26200.
 
    .INPUTS
        None. This function does not accept pipeline input.
 
    .OUTPUTS
        System.Management.Automation.PSCustomObject. Returns the selected Windows RE source,
        or no object when none is selected or available.
 
    .NOTES
        Author: David Segura
        Company: Recast Software
        Version: 0.1.0
        Date: 2026-08-28
 
    .LINK
        Get-OSDeployCoreWindowsRE
    #>

    [CmdletBinding()]
    param (
        [ValidateSet('amd64', 'arm64')]
        [System.String]
        $Architecture,

        [ValidateSet(26200, 26300)]
        [int]
        $BuildMajor
    )

    $params = @{}
    if ($Architecture) { $params.Architecture = $Architecture }

    $results = Get-OSDeployCoreWindowsRE @params
    if ($PSBoundParameters.ContainsKey('BuildMajor') -and $results) {
        $results = $results | Where-Object { ([version]$_.OSVersion).Build -eq $BuildMajor }
    }

    if ($results) {
        if (@($results).Count -eq 1) {
            Write-HostDateTimeDarkGray 'Auto-selected the only available Windows Recovery Image'
            return $results
        }

        Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] Recovery Images: $env:ProgramData\OSDeployCore\cache\windows-re"

        if ([Console]::IsInputRedirected -or [Console]::IsOutputRedirected) {
            Write-Warning "[$(Get-Date -Format s)] An interactive console is required to select a Windows Recovery Image"
            return
        }

        $resultItems = @($results)
        $displayResults = @($resultItems | Select-Object Name, Architecture, OSVersion, Version, Languages, ImageSize)
        $columnNames = @('Name', 'Architecture', 'OSVersion', 'Version', 'Languages', 'ImageSize')
        $tableRows = for ($resultIndex = 0; $resultIndex -lt $displayResults.Count; $resultIndex++) {
            $displayResult = $displayResults[$resultIndex]
            [PSCustomObject]@{
                Result = $resultItems[$resultIndex]
                Values = @($columnNames | ForEach-Object { [string]$displayResult.$_ })
            }
        }

        $columnWidths = foreach ($columnIndex in 0..($columnNames.Count - 1)) {
            $maximumValueLength = ($tableRows | ForEach-Object { $_.Values[$columnIndex].Length } | Measure-Object -Maximum).Maximum
            [Math]::Max($columnNames[$columnIndex].Length, $maximumValueLength)
        }

        $header = (($columnNames | ForEach-Object -Begin { $columnIndex = 0 } -Process {
                    $value = $_.PadRight($columnWidths[$columnIndex])
                    $columnIndex++
                    $value
                }) -join ' ')

        $selectedIndex = 0
        $consoleTop = [Console]::CursorTop
        do {
            [Console]::SetCursorPosition(0, $consoleTop)
            Write-Host
            Write-Host -ForegroundColor Cyan "Select a Recovery Image (Up/Down to select, Enter to continue, Escape to cancel)"
            Write-Host $header

            for ($rowIndex = 0; $rowIndex -lt $tableRows.Count; $rowIndex++) {
                $tableRow = (($tableRows[$rowIndex].Values | ForEach-Object -Begin { $columnIndex = 0 } -Process {
                                $value = $_.PadRight($columnWidths[$columnIndex])
                                $columnIndex++
                                $value
                            }) -join ' ')

                if ($rowIndex -eq $selectedIndex) {
                    Write-Host "> $tableRow" -ForegroundColor Black -BackgroundColor Cyan
                }
                else {
                    Write-Host " $tableRow"
                }
            }

            $key = [Console]::ReadKey($true).Key
            switch ($key) {
                'UpArrow' { if ($selectedIndex -gt 0) { $selectedIndex-- } }
                'DownArrow' { if ($selectedIndex -lt ($tableRows.Count - 1)) { $selectedIndex++ } }
                'Escape' {
                    [Console]::WriteLine()
                    return
                }
            }
        } until ($key -eq 'Enter')

        [Console]::WriteLine()
        return $tableRows[$selectedIndex].Result
    }
    else {
        Write-Warning "[$(Get-Date -Format s)] No WinRE sources available for selection"
        return $null
    }
}