Improves USB drive selection for same-model drives

Preserves multiple selected drives that share the same model by storing an array of UniqueIds per model.

Updates drive discovery and UI restore logic to accept either a single UniqueId or a list, preventing missed selections and skipping duplicate additions.
This commit is contained in:
rbalsleyMSFT
2026-02-03 13:37:58 -08:00
parent 1feed40962
commit ed0266029a
2 changed files with 82 additions and 32 deletions
+49 -30
View File
@@ -195,9 +195,11 @@ Path to a JSON file containing a list of user-defined applications to install. D
.PARAMETER USBDriveList .PARAMETER USBDriveList
A hashtable containing USB drives from win32_diskdrive where: A hashtable containing USB drives from win32_diskdrive where:
- Key: USB drive model name (partial match supported) - Key: USB drive model name (partial match supported)
- Value: USB drive serial number (trailing partial match supported due to some serial numbers ending with blank spaces) - Value: USB drive UniqueId string, or an array of UniqueIds (to support selecting multiple drives with the same model)
Example: @{ "SanDisk Ultra" = "1234567890"; "Kingston DataTraveler" = "0987654321" } Examples:
@{ "SanDisk Ultra" = "1234567890" }
@{ "SanDisk Ultra" = @("1234567890", "ABCDEFG"); "Kingston DataTraveler" = "0987654321" }
.PARAMETER MaxUSBDrives .PARAMETER MaxUSBDrives
Maximum number of USB drives to build in parallel. Default is 5. Set to 0 to process all discovered drives (or all selected drives when USBDriveList or selection is used). Actual throttle will never exceed the number of drives discovered. Maximum number of USB drives to build in parallel. Default is 5. Set to 0 to process all discovered drives (or all selected drives when USBDriveList or selection is used). Actual throttle will never exceed the number of drives discovered.
@@ -3961,40 +3963,57 @@ Function Get-USBDrive {
} }
elseif ($USBDriveList) { elseif ($USBDriveList) {
# Log the count of specified USB drives # Log the count of specified USB drives
$USBDriveListCount = $USBDriveList.Count # USBDriveList values can be a single UniqueId string, or an array of UniqueIds (multiple same-model drives)
$USBDriveListCount = 0
foreach ($model in $USBDriveList.Keys) {
$USBDriveListCount += @($USBDriveList[$model]).Count
}
WriteLog "Looking for $USBDriveListCount USB drives from USB Drive List" WriteLog "Looking for $USBDriveListCount USB drives from USB Drive List"
# Get only the specified USB drives based on model and UniqueId # Get only the specified USB drives based on model and UniqueId
$USBDrives = @() $USBDrives = @()
foreach ($model in $USBDriveList.Keys) { foreach ($model in $USBDriveList.Keys) {
$configUniqueId = $USBDriveList[$model] $configUniqueIds = @($USBDriveList[$model])
WriteLog "Looking for USB drive model $model with UniqueId $configUniqueId"
# First get candidate drives by model and media type foreach ($configUniqueId in $configUniqueIds) {
$candidateDrives = Get-CimInstance -ClassName Win32_DiskDrive -Filter "Model LIKE '%$model%' AND (MediaType='Removable Media' OR MediaType='External hard disk media')" if ([string]::IsNullOrWhiteSpace([string]$configUniqueId)) {
$foundDrive = $null continue
foreach ($candidate in $candidateDrives) { }
# Get the disk to retrieve UniqueId
$disk = Get-Disk -Number $candidate.Index -ErrorAction SilentlyContinue WriteLog "Looking for USB drive model $model with UniqueId $configUniqueId"
if ($disk -and $disk.UniqueId) { # First get candidate drives by model and media type
# Trim the machine name suffix (everything after the colon) from UniqueId $candidateDrives = Get-CimInstance -ClassName Win32_DiskDrive -Filter "Model LIKE '%$model%' AND (MediaType='Removable Media' OR MediaType='External hard disk media')"
$diskUniqueId = if ($disk.UniqueId -match ':') { $foundDrive = $null
$disk.UniqueId.Split(':')[0] foreach ($candidate in $candidateDrives) {
} # Get the disk to retrieve UniqueId
else { $disk = Get-Disk -Number $candidate.Index -ErrorAction SilentlyContinue
$disk.UniqueId if ($disk -and $disk.UniqueId) {
} # Trim the machine name suffix (everything after the colon) from UniqueId
# Match on the trimmed UniqueId $diskUniqueId = if ($disk.UniqueId -match ':') {
if ($diskUniqueId -eq $configUniqueId) { $disk.UniqueId.Split(':')[0]
$foundDrive = $candidate }
break else {
$disk.UniqueId
}
# Match on the trimmed UniqueId
if ($diskUniqueId -eq $configUniqueId) {
$foundDrive = $candidate
break
}
} }
} }
} if ($foundDrive) {
if ($foundDrive) { if ($USBDrives.Index -notcontains $foundDrive.Index) {
WriteLog "Found USB drive model $($foundDrive.Model) with UniqueId $configUniqueId" WriteLog "Found USB drive model $($foundDrive.Model) with UniqueId $configUniqueId"
$USBDrives += $foundDrive $USBDrives += $foundDrive
} }
else { else {
WriteLog "USB drive model $model with UniqueId $configUniqueId not found" WriteLog "USB drive model $($foundDrive.Model) with UniqueId $configUniqueId was already added. Skipping duplicate."
}
}
else {
WriteLog "USB drive model $model with UniqueId $configUniqueId not found"
}
} }
} }
$USBDrivesCount = $USBDrives.Count $USBDrivesCount = $USBDrives.Count
@@ -115,8 +115,27 @@ function Get-UIConfig {
} }
# Save selected USB drives using UniqueId for reliable identification # Save selected USB drives using UniqueId for reliable identification
# Multiple physical drives can share the same Model, so store an array of UniqueIds per Model.
$State.Controls.lstUSBDrives.Items | Where-Object { $_.IsSelected } | ForEach-Object { $State.Controls.lstUSBDrives.Items | Where-Object { $_.IsSelected } | ForEach-Object {
$config.USBDriveList[$_.Model] = $_.UniqueId $modelName = $_.Model
$uniqueId = $_.UniqueId
if ([string]::IsNullOrWhiteSpace($modelName) -or [string]::IsNullOrWhiteSpace($uniqueId)) {
return
}
# Ensure the hashtable value is always an array so multiple same-model drives are preserved
$existingUniqueIds = $config.USBDriveList[$modelName]
if ($null -eq $existingUniqueIds) {
$config.USBDriveList[$modelName] = @($uniqueId)
return
}
$existingUniqueIds = @($existingUniqueIds)
if (-not ($existingUniqueIds -contains $uniqueId)) {
$existingUniqueIds += $uniqueId
}
$config.USBDriveList[$modelName] = $existingUniqueIds
} }
# Additional FFU file selections # Additional FFU file selections
@@ -671,7 +690,19 @@ function Update-UIFromConfig {
} }
# Match USB drives by UniqueId instead of SerialNumber # Match USB drives by UniqueId instead of SerialNumber
if ($propertyExists -and ($propertyValue -eq $item.UniqueId)) { # USBDriveList values can be a single UniqueId (string) or an array of UniqueIds (multiple same-model drives)
$isMatch = $false
if ($propertyExists) {
if ($propertyValue -is [string]) {
$isMatch = ($propertyValue -eq $item.UniqueId)
}
else {
$propertyValueArray = @($propertyValue)
$isMatch = ($propertyValueArray -contains $item.UniqueId)
}
}
if ($isMatch) {
WriteLog "LoadConfig: Selecting USB Drive Model '$($item.Model)' with UniqueId '$($item.UniqueId)'." WriteLog "LoadConfig: Selecting USB Drive Model '$($item.Model)' with UniqueId '$($item.UniqueId)'."
$item.IsSelected = $true $item.IsSelected = $true
} }