Skip to content

Commit dfa43be

Browse files
committed
Fix persistent FAT32 format failure: single-pass diskpart script (v3.2.2)
Fixes #49 — FAT32 format still failing on v3.2.0 despite automount disable Root cause: The v3.1.9 automount fix used two separate diskpart processes (Phase 1: create partition, Phase 2: format). automount disable only persists within the diskpart session on some Windows 10 builds. Between Phase 1 exiting and Phase 2 launching (~1.5s gap), Explorer re-acquired a handle on the raw partition, causing the format to fail even with automount disabled. Fix: Merged Phase 1 and Phase 2 into a single diskpart script that runs clean → convert gpt → create partition → format fs=fat32 → assign in ONE diskpart session. This eliminates the inter-process window entirely. The single-pass script uses noerr on safe preliminary commands (clean, convert, create) but NOT on the format command so failures still surface immediately (preserving #38/#41 fix). Phase 2 remains as a fallback only if the single-pass format step fails for other reasons (e.g. drive controller issue).
1 parent 3dbfadc commit dfa43be

3 files changed

Lines changed: 16 additions & 10 deletions

File tree

electron/diskOps.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,11 +232,12 @@ export function isWindowsUsbLikeDisk(input: {
232232
}
233233

234234
export function buildWindowsFlashDiskpartScript(diskNum: string, partitionSizeMB?: number): string {
235+
// Single-pass diskpart script: clean → create → format → assign in ONE session.
236+
// Previous design used two separate diskpart invocations (Phase 1: create, Phase 2: format).
237+
// This caused persistent FAT32 format failures (#48, #49) because Explorer/Shell auto-mounts
238+
// the raw partition in the gap between the two processes, locking it before format can run.
239+
// Merging into one session eliminates the inter-process window entirely.
235240
return [
236-
// Disable automount BEFORE creating the partition to prevent Explorer
237-
// from immediately grabbing a handle on the new raw volume.
238-
// This is the root cause of FAT32 format failures (#48): Explorer
239-
// auto-mounts the partition between create and format, locking it.
240241
'automount disable',
241242
`select disk ${diskNum}`,
242243
'attributes disk clear readonly noerr',
@@ -247,6 +248,11 @@ export function buildWindowsFlashDiskpartScript(diskNum: string, partitionSizeMB
247248
partitionSizeMB && partitionSizeMB > 0
248249
? `create partition primary size=${partitionSizeMB} noerr`
249250
: 'create partition primary noerr',
251+
// Format WITHOUT noerr so failures surface immediately (#38, #41).
252+
// Running in the same session as create eliminates the Explorer lock race (#48, #49).
253+
'format fs=fat32 quick label=OPENCORE',
254+
'assign noerr',
255+
'automount enable',
250256
'rescan',
251257
'',
252258
].join('\n');

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "opcore-oneclick",
33
"private": true,
4-
"version": "3.2.1",
4+
"version": "3.2.2",
55
"description": "OpCore-OneClick deployment utility",
66
"author": "OpCore-OneClick contributors",
77
"main": "dist-electron/electron/main.js",

test/diskOps.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,10 @@ describe('buildWindowsFlashDiskpartScript', () => {
170170
expect(script).toContain('convert gpt noerr');
171171
});
172172

173-
it('does NOT contain format or assign (moved to phase 2)', () => {
173+
it('contains format and assign in single-pass script (#48, #49)', () => {
174174
const script = buildWindowsFlashDiskpartScript('0');
175-
expect(script).not.toContain('format fs=fat32');
176-
expect(script).not.toContain('assign noerr');
175+
expect(script).toContain('format fs=fat32 quick label=OPENCORE');
176+
expect(script).toContain('assign noerr');
177177
});
178178
});
179179

@@ -220,9 +220,9 @@ describe('buildWindowsConvertToGptDiskpartScript', () => {
220220
expect(script).toContain('rescan');
221221
});
222222

223-
it('does NOT contain format (moved to phase 2 script)', () => {
223+
it('contains format in single-pass script (#48, #49)', () => {
224224
const script = buildWindowsConvertToGptDiskpartScript('2');
225-
expect(script).not.toContain('format fs=fat32');
225+
expect(script).toContain('format fs=fat32 quick label=OPENCORE');
226226
});
227227

228228
it('uses the Windows FAT32 size cap when provided', () => {

0 commit comments

Comments
 (0)