Skip to content

Commit c0260bd

Browse files
Fix usb error on drive with no existing partitions
1 parent 9769caf commit c0260bd

File tree

1 file changed

+35
-8
lines changed

1 file changed

+35
-8
lines changed

functions/private/Invoke-WinUtilISOUSB.ps1

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,24 @@ function Invoke-WinUtilISOWriteUSB {
103103
try {
104104
SetProgress "Formatting USB drive..." 10
105105

106-
# Phase 1: Clean disk via diskpart
106+
# Phase 1: Clean disk via diskpart (retry once if the drive is not yet ready)
107107
$dpFile1 = Join-Path $env:TEMP "winutil_diskpart_$(Get-Random).txt"
108108
"select disk $diskNum`nclean`nexit" | Set-Content -Path $dpFile1 -Encoding ASCII
109109
Log "Running diskpart clean on Disk $diskNum..."
110-
diskpart /s $dpFile1 2>&1 | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" }
110+
$dpCleanOut = diskpart /s $dpFile1 2>&1
111+
$dpCleanOut | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" }
111112
Remove-Item $dpFile1 -Force -ErrorAction SilentlyContinue
112113

114+
if (($dpCleanOut -join ' ') -match 'device is not ready') {
115+
Log "Disk $diskNum was not ready; waiting 5 seconds and retrying clean..."
116+
Start-Sleep -Seconds 5
117+
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue
118+
$dpFile1b = Join-Path $env:TEMP "winutil_diskpart_$(Get-Random).txt"
119+
"select disk $diskNum`nclean`nexit" | Set-Content -Path $dpFile1b -Encoding ASCII
120+
diskpart /s $dpFile1b 2>&1 | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" }
121+
Remove-Item $dpFile1b -Force -ErrorAction SilentlyContinue
122+
}
123+
113124
# Phase 2: Initialize as GPT
114125
Start-Sleep -Seconds 2
115126
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue
@@ -122,7 +133,8 @@ function Invoke-WinUtilISOWriteUSB {
122133
Log "Disk $diskNum converted to GPT (was $($diskObj.PartitionStyle))."
123134
}
124135

125-
# Phase 3: Create FAT32 partition via diskpart
136+
# Phase 3: Create FAT32 partition via diskpart, then format with Format-Volume
137+
# (diskpart's 'format' command can fail with "no volume selected" on fresh/never-formatted drives)
126138
$volLabel = "W11-" + (Get-Date).ToString('yyMMdd')
127139
$dpFile2 = Join-Path $env:TEMP "winutil_diskpart2_$(Get-Random).txt"
128140
$maxFat32PartitionMB = 32768
@@ -136,29 +148,38 @@ function Invoke-WinUtilISOWriteUSB {
136148
@(
137149
"select disk $diskNum"
138150
$createPartitionCommand
139-
"select partition 1"
140-
"format quick fs=fat32 label=`"$volLabel`""
141151
"exit"
142152
) | Set-Content -Path $dpFile2 -Encoding ASCII
143153
Log "Creating partitions on Disk $diskNum..."
144154
diskpart /s $dpFile2 2>&1 | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" }
145155
Remove-Item $dpFile2 -Force -ErrorAction SilentlyContinue
146156

147-
SetProgress "Assigning drive letters..." 30
157+
SetProgress "Formatting USB partition..." 25
148158
Start-Sleep -Seconds 3
149159
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue
150160

151161
$partitions = Get-Partition -DiskNumber $diskNum -ErrorAction Stop
152-
Log "Partitions on Disk $diskNum after format: $($partitions.Count)"
162+
Log "Partitions on Disk $diskNum after creation: $($partitions.Count)"
153163
foreach ($p in $partitions) {
154164
Log " Partition $($p.PartitionNumber) Type=$($p.Type) Letter=$($p.DriveLetter) Size=$([math]::Round($p.Size/1MB))MB"
155165
}
156166

157167
$winpePart = $partitions | Where-Object { $_.Type -eq "Basic" } | Select-Object -Last 1
158168
if (-not $winpePart) {
159-
throw "Could not find the WINPE (Basic) partition on Disk $diskNum after format."
169+
throw "Could not find the Basic partition on Disk $diskNum after creation."
160170
}
161171

172+
# Format using Format-Volume (reliable on fresh drives; diskpart format fails
173+
# with 'no volume selected' when the partition has never been formatted before)
174+
Log "Formatting Partition $($winpePart.PartitionNumber) as FAT32 (label: $volLabel)..."
175+
Get-Partition -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber |
176+
Format-Volume -FileSystem FAT32 -NewFileSystemLabel $volLabel -Force -Confirm:$false | Out-Null
177+
Log "Partition $($winpePart.PartitionNumber) formatted as FAT32."
178+
179+
SetProgress "Assigning drive letters..." 30
180+
Start-Sleep -Seconds 2
181+
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue
182+
162183
try { Remove-PartitionAccessPath -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber -AccessPath "$($winpePart.DriveLetter):" -ErrorAction SilentlyContinue } catch {}
163184
$usbLetter = Get-FreeDriveLetter
164185
if (-not $usbLetter) { throw "No free drive letters (D-Z) available to assign to the USB data partition." }
@@ -167,6 +188,12 @@ function Invoke-WinUtilISOWriteUSB {
167188
Start-Sleep -Seconds 2
168189

169190
$usbDrive = "${usbLetter}:"
191+
$retries = 0
192+
while (-not (Test-Path $usbDrive) -and $retries -lt 6) {
193+
$retries++
194+
Log "Waiting for $usbDrive to become accessible (attempt $retries/6)..."
195+
Start-Sleep -Seconds 2
196+
}
170197
if (-not (Test-Path $usbDrive)) { throw "Drive $usbDrive is not accessible after letter assignment." }
171198
Log "USB data partition: $usbDrive"
172199

0 commit comments

Comments
 (0)