private/Select-OSDeployDiskUSBCLI.ps1
|
function Select-OSDeployDiskUSBCLI { <# .SYNOPSIS Selects a USB disk in a native console picker .DESCRIPTION Uses supplied disk objects or discovers USB disks with Get-OSDeployDisk, then excludes disks outside the configured size limits. Eligible disks are displayed in a native console table that supports Up and Down arrow navigation, Enter to select, and Escape to cancel. SelectOne returns a sole eligible disk without displaying the picker. Multiple-disk selection requires a nonredirected console. Escape returns Boolean false when Skip is specified and otherwise returns no object. This function does not modify disks. .PARAMETER Input Specifies disk objects to filter and select instead of calling Get-OSDeployDisk. This parameter accepts pipeline input. .PARAMETER MinimumSizeGB Specifies the exclusive minimum disk size in GiB. Default is 8. Aliases are Min, MinGB, and MinSize. .PARAMETER MaximumSizeGB Specifies the exclusive maximum disk size in GiB. Default is 1800. Aliases are Max, MaxGB, and MaxSize. .PARAMETER Skip Returns Boolean false when the user presses Escape in the console picker. .PARAMETER SelectOne Returns the eligible disk automatically when exactly one disk is available. .EXAMPLE PS> Select-OSDeployDiskUSBCLI -MinimumSizeGB 16 -MaximumSizeGB 256 -Skip Displays eligible USB disks in the console picker and returns false if Escape is pressed. .INPUTS System.Object. Accepts disk objects through Input. .OUTPUTS Microsoft.Management.Infrastructure.CimInstance. Returns the selected MSFT_Disk object. System.Boolean. Returns false when Skip is specified and the user presses Escape. .NOTES Author: David Segura Company: Recast Software Version: 1.0.0 Date: 2026-08-28 Multiple-result selection requires an interactive console. .LINK Get-OSDeployDisk #> [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true)] [Object]$Input, [Alias('Min','MinGB','MinSize')] [int]$MinimumSizeGB = 8, [Alias('Max','MaxGB','MaxSize')] [int]$MaximumSizeGB = 1800, [System.Management.Automation.SwitchParameter]$Skip, [System.Management.Automation.SwitchParameter]$SelectOne ) #================================================= # Get-Disk #================================================= if ($Input) { $Results = $Input } else { $Results = Get-OSDeployDisk -BusType USB | Where-Object {($_.Size -gt ($MinimumSizeGB * 1GB)) -and ($_.Size -lt ($MaximumSizeGB * 1GB))} } #================================================= # Process Results #================================================= if ($Results) { #================================================= # There was only 1 Item, then we will select it automatically #================================================= if ($PSBoundParameters.ContainsKey('SelectOne')) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Automatically select " if (($Results | Measure-Object).Count -eq 1) { $SelectedItem = $Results Return $SelectedItem } } #================================================= # Select an Item #================================================= $DisplayResults = @($Results | Select-Object -Property Number, BusType, MediaType,` @{Name='SizeGB';Expression={[int]($_.Size / 1GB)}},` FriendlyName, Model, PartitionStyle,` @{Name='Partitions';Expression={$_.NumberOfPartitions}}) if ([Console]::IsInputRedirected -or [Console]::IsOutputRedirected) { Write-Warning "[$(Get-Date -Format s)] An interactive console is required to select a USB disk" return } $columnNames = @('Number', 'BusType', 'MediaType', 'SizeGB', 'FriendlyName', 'Model', 'PartitionStyle', 'Partitions') $tableRows = foreach ($row in $DisplayResults) { [PSCustomObject]@{ Disk = $row Values = @($columnNames | ForEach-Object { [string]$row.$_ }) } } $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 DarkGreen 'Select a USB Disk (Up/Down to select, Enter to continue, Escape to cancel)' Write-Host -ForegroundColor DarkGray $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() if ($PSBoundParameters.ContainsKey('Skip')) { return $false } return } } } until ($key -eq 'Enter') [Console]::WriteLine() Return ($Results | Where-Object { $_.Number -eq $tableRows[$selectedIndex].Disk.Number }) #================================================= } } |