Strip unneccary surpassion from win11 creator (#4422)

* Update Invoke-WinUtilISO.ps1

* Update Invoke-WinUtilISOScript.ps1

* Update Invoke-WinUtilISOUSB.ps1

* Merge branch 'ChrisTitusTech:main' into patch-8
This commit is contained in:
Gabi
2026-04-30 22:58:07 +03:00
committed by GitHub
parent 10d83c5b20
commit 9d4613d838
3 changed files with 85 additions and 85 deletions
+39 -39
View File
@@ -49,7 +49,7 @@ function Invoke-WinUtilISOMountAndVerify {
Set-WinUtilProgressBar -Label "Mounting ISO..." -Percent 10 Set-WinUtilProgressBar -Label "Mounting ISO..." -Percent 10
try { try {
Mount-DiskImage -ImagePath $isoPath -ErrorAction Stop | Out-Null Mount-DiskImage -ImagePath $isoPath
do { do {
Start-Sleep -Milliseconds 500 Start-Sleep -Milliseconds 500
@@ -64,7 +64,7 @@ function Invoke-WinUtilISOMountAndVerify {
$esdPath = Join-Path $driveLetter "sources\install.esd" $esdPath = Join-Path $driveLetter "sources\install.esd"
if (-not (Test-Path $wimPath) -and -not (Test-Path $esdPath)) { if (-not (Test-Path $wimPath) -and -not (Test-Path $esdPath)) {
Dismount-DiskImage -ImagePath $isoPath | Out-Null Dismount-DiskImage -ImagePath $isoPath
Write-Win11ISOLog "ERROR: install.wim/install.esd not found — not a valid Windows ISO." Write-Win11ISOLog "ERROR: install.wim/install.esd not found — not a valid Windows ISO."
[System.Windows.MessageBox]::Show( [System.Windows.MessageBox]::Show(
"This does not appear to be a valid Windows ISO.`n`ninstall.wim / install.esd was not found.", "This does not appear to be a valid Windows ISO.`n`ninstall.wim / install.esd was not found.",
@@ -79,7 +79,7 @@ function Invoke-WinUtilISOMountAndVerify {
$imageInfo = Get-WindowsImage -ImagePath $activeWim | Select-Object ImageIndex, ImageName $imageInfo = Get-WindowsImage -ImagePath $activeWim | Select-Object ImageIndex, ImageName
if (-not ($imageInfo | Where-Object { $_.ImageName -match "Windows 11" })) { if (-not ($imageInfo | Where-Object { $_.ImageName -match "Windows 11" })) {
Dismount-DiskImage -ImagePath $isoPath | Out-Null Dismount-DiskImage -ImagePath $isoPath
Write-Win11ISOLog "ERROR: No 'Windows 11' edition found in the image." Write-Win11ISOLog "ERROR: No 'Windows 11' edition found in the image."
[System.Windows.MessageBox]::Show( [System.Windows.MessageBox]::Show(
"No Windows 11 edition was found in this ISO.`n`nOnly official Windows 11 ISOs are supported.", "No Windows 11 edition was found in this ISO.`n`nOnly official Windows 11 ISOs are supported.",
@@ -151,7 +151,7 @@ function Invoke-WinUtilISOModify {
$sync["WPFWin11ISOModifyButton"].IsEnabled = $false $sync["WPFWin11ISOModifyButton"].IsEnabled = $false
$sync["Win11ISOModifying"] = $true $sync["Win11ISOModifying"] = $true
$existingWorkDir = Get-Item -Path (Join-Path $env:TEMP "WinUtil_Win11ISO*") -ErrorAction SilentlyContinue | $existingWorkDir = Get-Item -Path (Join-Path $env:TEMP "WinUtil_Win11ISO*") |
Where-Object { $_.PSIsContainer } | Sort-Object LastWriteTime -Descending | Select-Object -First 1 Where-Object { $_.PSIsContainer } | Sort-Object LastWriteTime -Descending | Select-Object -First 1
$workDir = if ($existingWorkDir) { $workDir = if ($existingWorkDir) {
@@ -202,7 +202,7 @@ function Invoke-WinUtilISOModify {
$sync["WPFWin11ISOStatusLog"].CaretIndex = $sync["WPFWin11ISOStatusLog"].Text.Length $sync["WPFWin11ISOStatusLog"].CaretIndex = $sync["WPFWin11ISOStatusLog"].Text.Length
$sync["WPFWin11ISOStatusLog"].ScrollToEnd() $sync["WPFWin11ISOStatusLog"].ScrollToEnd()
}) })
Add-Content -Path (Join-Path $workDir "WinUtil_Win11ISO.log") -Value "[$ts] $msg" -ErrorAction SilentlyContinue Add-Content -Path (Join-Path $workDir "WinUtil_Win11ISO.log") -Value "[$ts] $msg"
} }
function SetProgress($label, $pct) { function SetProgress($label, $pct) {
@@ -223,11 +223,11 @@ function Invoke-WinUtilISOModify {
Log "Creating working directory: $workDir" Log "Creating working directory: $workDir"
$isoContents = Join-Path $workDir "iso_contents" $isoContents = Join-Path $workDir "iso_contents"
$mountDir = Join-Path $workDir "wim_mount" $mountDir = Join-Path $workDir "wim_mount"
New-Item -ItemType Directory -Path $isoContents, $mountDir -Force | Out-Null New-Item -ItemType Directory -Path $isoContents, $mountDir -Force
SetProgress "Copying ISO contents..." 10 SetProgress "Copying ISO contents..." 10
Log "Copying ISO contents from $driveLetter to $isoContents..." Log "Copying ISO contents from $driveLetter to $isoContents..."
& robocopy $driveLetter $isoContents /E /NFL /NDL /NJH /NJS | Out-Null & robocopy $driveLetter $isoContents /E /NFL /NDL /NJH /NJS
Log "ISO contents copied." Log "ISO contents copied."
SetProgress "Mounting install.wim..." 25 SetProgress "Mounting install.wim..." 25
@@ -236,7 +236,7 @@ function Invoke-WinUtilISOModify {
Set-ItemProperty -Path $localWim -Name IsReadOnly -Value $false Set-ItemProperty -Path $localWim -Name IsReadOnly -Value $false
Log "Mounting install.wim (Index ${selectedWimIndex}: $selectedEditionName) at $mountDir..." Log "Mounting install.wim (Index ${selectedWimIndex}: $selectedEditionName) at $mountDir..."
Mount-WindowsImage -ImagePath $localWim -Index $selectedWimIndex -Path $mountDir -ErrorAction Stop | Out-Null Mount-WindowsImage -ImagePath $localWim -Index $selectedWimIndex -Path $mountDir
SetProgress "Modifying install.wim..." 45 SetProgress "Modifying install.wim..." 45
Log "Applying WinUtil modifications to install.wim..." Log "Applying WinUtil modifications to install.wim..."
@@ -249,13 +249,13 @@ function Invoke-WinUtilISOModify {
SetProgress "Saving modified install.wim..." 65 SetProgress "Saving modified install.wim..." 65
Log "Dismounting and saving install.wim. This will take several minutes..." Log "Dismounting and saving install.wim. This will take several minutes..."
Dismount-WindowsImage -Path $mountDir -Save -ErrorAction Stop | Out-Null Dismount-WindowsImage -Path $mountDir -Save
Log "install.wim saved." Log "install.wim saved."
SetProgress "Removing unused editions from install.wim..." 70 SetProgress "Removing unused editions from install.wim..." 70
Log "Exporting edition '$selectedEditionName' (Index $selectedWimIndex) to a single-edition install.wim..." Log "Exporting edition '$selectedEditionName' (Index $selectedWimIndex) to a single-edition install.wim..."
$exportWim = Join-Path $isoContents "sources\install_export.wim" $exportWim = Join-Path $isoContents "sources\install_export.wim"
Export-WindowsImage -SourceImagePath $localWim -SourceIndex $selectedWimIndex -DestinationImagePath $exportWim -ErrorAction Stop | Out-Null Export-WindowsImage -SourceImagePath $localWim -SourceIndex $selectedWimIndex -DestinationImagePath $exportWim
Remove-Item -Path $localWim -Force Remove-Item -Path $localWim -Force
Rename-Item -Path $exportWim -NewName "install.wim" -Force Rename-Item -Path $exportWim -NewName "install.wim" -Force
$localWim = Join-Path $isoContents "sources\install.wim" $localWim = Join-Path $isoContents "sources\install.wim"
@@ -263,7 +263,7 @@ function Invoke-WinUtilISOModify {
SetProgress "Dismounting source ISO..." 80 SetProgress "Dismounting source ISO..." 80
Log "Dismounting original ISO..." Log "Dismounting original ISO..."
Dismount-DiskImage -ImagePath $isoPath | Out-Null Dismount-DiskImage -ImagePath $isoPath
$sync["Win11ISOWorkDir"] = $workDir $sync["Win11ISOWorkDir"] = $workDir
$sync["Win11ISOContentsDir"] = $isoContents $sync["Win11ISOContentsDir"] = $isoContents
@@ -279,26 +279,26 @@ function Invoke-WinUtilISOModify {
try { try {
if (Test-Path $mountDir) { if (Test-Path $mountDir) {
$mountedImages = Get-WindowsImage -Mounted -ErrorAction SilentlyContinue | Where-Object { $_.Path -eq $mountDir } $mountedImages = Get-WindowsImage -Mounted | Where-Object { $_.Path -eq $mountDir }
if ($mountedImages) { if ($mountedImages) {
Log "Cleaning up: dismounting install.wim (discarding changes)..." Log "Cleaning up: dismounting install.wim (discarding changes)..."
Dismount-WindowsImage -Path $mountDir -Discard -ErrorAction SilentlyContinue | Out-Null Dismount-WindowsImage -Path $mountDir -Discard
} }
} }
} catch { Log "Warning: could not dismount install.wim during cleanup: $_" } } catch { Log "Warning: could not dismount install.wim during cleanup: $_" }
try { try {
$mountedISO = Get-DiskImage -ImagePath $isoPath -ErrorAction SilentlyContinue $mountedISO = Get-DiskImage -ImagePath $isoPath
if ($mountedISO -and $mountedISO.Attached) { if ($mountedISO -and $mountedISO.Attached) {
Log "Cleaning up: dismounting source ISO..." Log "Cleaning up: dismounting source ISO..."
Dismount-DiskImage -ImagePath $isoPath -ErrorAction SilentlyContinue | Out-Null Dismount-DiskImage -ImagePath $isoPath
} }
} catch { Log "Warning: could not dismount ISO during cleanup: $_" } } catch { Log "Warning: could not dismount ISO during cleanup: $_" }
try { try {
if (Test-Path $workDir) { if (Test-Path $workDir) {
Log "Cleaning up: removing temp directory $workDir..." Log "Cleaning up: removing temp directory $workDir..."
Remove-Item -Path $workDir -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path $workDir -Recurse -Force
} }
} catch { Log "Warning: could not remove temp directory during cleanup: $_" } } catch { Log "Warning: could not remove temp directory during cleanup: $_" }
@@ -322,9 +322,9 @@ function Invoke-WinUtilISOModify {
} }
}) })
} }
}) | Out-Null })
$script.BeginInvoke() | Out-Null $script.BeginInvoke()
} }
function Invoke-WinUtilISOCheckExistingWork { function Invoke-WinUtilISOCheckExistingWork {
@@ -335,7 +335,7 @@ function Invoke-WinUtilISOCheckExistingWork {
return return
} }
$existingWorkDir = Get-Item -Path (Join-Path $env:TEMP "WinUtil_Win11ISO*") -ErrorAction SilentlyContinue | $existingWorkDir = Get-Item -Path (Join-Path $env:TEMP "WinUtil_Win11ISO*") |
Where-Object { $_.PSIsContainer } | Sort-Object LastWriteTime -Descending | Select-Object -First 1 Where-Object { $_.PSIsContainer } | Sort-Object LastWriteTime -Descending | Select-Object -First 1
if (-not $existingWorkDir) { return } if (-not $existingWorkDir) { return }
@@ -391,7 +391,7 @@ function Invoke-WinUtilISOCleanAndReset {
$sync["WPFWin11ISOStatusLog"].CaretIndex = $sync["WPFWin11ISOStatusLog"].Text.Length $sync["WPFWin11ISOStatusLog"].CaretIndex = $sync["WPFWin11ISOStatusLog"].Text.Length
$sync["WPFWin11ISOStatusLog"].ScrollToEnd() $sync["WPFWin11ISOStatusLog"].ScrollToEnd()
}) })
Add-Content -Path (Join-Path $workDir "WinUtil_Win11ISO.log") -Value "[$ts] $msg" -ErrorAction SilentlyContinue Add-Content -Path (Join-Path $workDir "WinUtil_Win11ISO.log") -Value "[$ts] $msg"
} }
function SetProgress($label, $pct) { function SetProgress($label, $pct) {
@@ -406,23 +406,23 @@ function Invoke-WinUtilISOCleanAndReset {
if ($workDir) { if ($workDir) {
$mountDir = Join-Path $workDir "wim_mount" $mountDir = Join-Path $workDir "wim_mount"
try { try {
$mountedImages = Get-WindowsImage -Mounted -ErrorAction SilentlyContinue | $mountedImages = Get-WindowsImage -Mounted |
Where-Object { $_.Path -like "$workDir*" } Where-Object { $_.Path -like "$workDir*" }
if ($mountedImages) { if ($mountedImages) {
foreach ($img in $mountedImages) { foreach ($img in $mountedImages) {
Log "Dismounting WIM at: $($img.Path) (discarding changes)..." Log "Dismounting WIM at: $($img.Path) (discarding changes)..."
SetProgress "Dismounting WIM image..." 3 SetProgress "Dismounting WIM image..." 3
Dismount-WindowsImage -Path $img.Path -Discard -ErrorAction Stop | Out-Null Dismount-WindowsImage -Path $img.Path -Discard
Log "WIM dismounted successfully." Log "WIM dismounted successfully."
} }
} elseif (Test-Path $mountDir) { } elseif (Test-Path $mountDir) {
Log "No mounted WIM reported by Get-WindowsImage. Running DISM /Cleanup-Wim as a precaution..." Log "No mounted WIM reported by Get-WindowsImage. Running DISM /Cleanup-Wim as a precaution..."
SetProgress "Running DISM cleanup..." 3 SetProgress "Running DISM cleanup..." 3
& dism /English /Cleanup-Wim 2>&1 | ForEach-Object { Log $_ } & dism /English /Cleanup-Wim | ForEach-Object { Log $_ }
} }
} catch { } catch {
Log "Warning: could not dismount WIM cleanly. Attempting DISM /Cleanup-Wim fallback: $_" Log "Warning: could not dismount WIM cleanly. Attempting DISM /Cleanup-Wim fallback: $_"
try { & dism /English /Cleanup-Wim 2>&1 | ForEach-Object { Log $_ } } try { & dism /English /Cleanup-Wim | ForEach-Object { Log $_ } }
catch { Log "Warning: DISM /Cleanup-Wim also failed: $_" } catch { Log "Warning: DISM /Cleanup-Wim also failed: $_" }
} }
} }
@@ -431,8 +431,8 @@ function Invoke-WinUtilISOCleanAndReset {
Log "Scanning files to delete in: $workDir" Log "Scanning files to delete in: $workDir"
SetProgress "Scanning files..." 5 SetProgress "Scanning files..." 5
$allFiles = @(Get-ChildItem -Path $workDir -File -Recurse -Force -ErrorAction SilentlyContinue) $allFiles = @(Get-ChildItem -Path $workDir -File -Recurse -Force)
$allDirs = @(Get-ChildItem -Path $workDir -Directory -Recurse -Force -ErrorAction SilentlyContinue | $allDirs = @(Get-ChildItem -Path $workDir -Directory -Recurse -Force |
Sort-Object { $_.FullName.Length } -Descending) Sort-Object { $_.FullName.Length } -Descending)
$total = $allFiles.Count $total = $allFiles.Count
$deleted = 0 $deleted = 0
@@ -440,7 +440,7 @@ function Invoke-WinUtilISOCleanAndReset {
Log "Found $total files to delete." Log "Found $total files to delete."
foreach ($f in $allFiles) { foreach ($f in $allFiles) {
try { Remove-Item -Path $f.FullName -Force -ErrorAction Stop } catch { Log "WARNING: could not delete $($f.FullName): $_" } try { Remove-Item -Path $f.FullName -Force } catch { Log "WARNING: could not delete $($f.FullName): $_" }
$deleted++ $deleted++
if ($deleted % 100 -eq 0 -or $deleted -eq $total) { if ($deleted % 100 -eq 0 -or $deleted -eq $total) {
$pct = [math]::Round(($deleted / [Math]::Max($total, 1)) * 85) + 5 $pct = [math]::Round(($deleted / [Math]::Max($total, 1)) * 85) + 5
@@ -449,10 +449,10 @@ function Invoke-WinUtilISOCleanAndReset {
} }
foreach ($d in $allDirs) { foreach ($d in $allDirs) {
try { Remove-Item -Path $d.FullName -Force -ErrorAction SilentlyContinue } catch {} try { Remove-Item -Path $d.FullName -Force } catch {}
} }
try { Remove-Item -Path $workDir -Recurse -Force -ErrorAction Stop } catch {} try { Remove-Item -Path $workDir -Recurse -Force } catch {}
if (Test-Path $workDir) { if (Test-Path $workDir) {
Log "WARNING: some items could not be deleted in $workDir" Log "WARNING: some items could not be deleted in $workDir"
@@ -501,9 +501,9 @@ function Invoke-WinUtilISOCleanAndReset {
$sync["WPFWin11ISOCleanResetButton"].IsEnabled = $true $sync["WPFWin11ISOCleanResetButton"].IsEnabled = $true
}) })
} }
}) | Out-Null })
$script.BeginInvoke() | Out-Null $script.BeginInvoke()
} }
function Invoke-WinUtilISOExport { function Invoke-WinUtilISOExport {
@@ -529,10 +529,10 @@ function Invoke-WinUtilISOExport {
$outputISO = $dlg.FileName $outputISO = $dlg.FileName
# Locate oscdimg.exe (Windows ADK or winget per-user install) # Locate oscdimg.exe (Windows ADK or winget per-user install)
$oscdimg = Get-ChildItem "C:\Program Files (x86)\Windows Kits" -Recurse -Filter "oscdimg.exe" -ErrorAction SilentlyContinue | $oscdimg = Get-ChildItem "C:\Program Files (x86)\Windows Kits" -Recurse -Filter "oscdimg.exe" |
Select-Object -First 1 -ExpandProperty FullName Select-Object -First 1 -ExpandProperty FullName
if (-not $oscdimg) { if (-not $oscdimg) {
$oscdimg = Get-ChildItem "$env:LOCALAPPDATA\Microsoft\WinGet\Packages" -Recurse -Filter "oscdimg.exe" -ErrorAction SilentlyContinue | $oscdimg = Get-ChildItem "$env:LOCALAPPDATA\Microsoft\WinGet\Packages" -Recurse -Filter "oscdimg.exe" |
Where-Object { $_.FullName -match 'Microsoft\.OSCDIMG' } | Where-Object { $_.FullName -match 'Microsoft\.OSCDIMG' } |
Select-Object -First 1 -ExpandProperty FullName Select-Object -First 1 -ExpandProperty FullName
} }
@@ -543,10 +543,10 @@ function Invoke-WinUtilISOExport {
# First ensure winget is installed and operational # First ensure winget is installed and operational
Install-WinUtilWinget Install-WinUtilWinget
$winget = Get-Command winget -ErrorAction Stop $winget = Get-Command winget
$result = & $winget install -e --id Microsoft.OSCDIMG --accept-package-agreements --accept-source-agreements 2>&1 $result = & $winget install -e --id Microsoft.OSCDIMG --accept-package-agreements --accept-source-agreements
Write-Win11ISOLog "winget output: $result" Write-Win11ISOLog "winget output: $result"
$oscdimg = Get-ChildItem "$env:LOCALAPPDATA\Microsoft\WinGet\Packages" -Recurse -Filter "oscdimg.exe" -ErrorAction SilentlyContinue | $oscdimg = Get-ChildItem "$env:LOCALAPPDATA\Microsoft\WinGet\Packages" -Recurse -Filter "oscdimg.exe" |
Where-Object { $_.FullName -match 'Microsoft\.OSCDIMG' } | Where-Object { $_.FullName -match 'Microsoft\.OSCDIMG' } |
Select-Object -First 1 -ExpandProperty FullName Select-Object -First 1 -ExpandProperty FullName
} catch { } catch {
@@ -609,7 +609,7 @@ function Invoke-WinUtilISOExport {
$proc = [System.Diagnostics.Process]::new() $proc = [System.Diagnostics.Process]::new()
$proc.StartInfo = $psi $proc.StartInfo = $psi
$proc.Start() | Out-Null $proc.Start()
# Stream stdout line-by-line as oscdimg runs # Stream stdout line-by-line as oscdimg runs
while (-not $proc.StandardOutput.EndOfStream) { while (-not $proc.StandardOutput.EndOfStream) {
@@ -653,7 +653,7 @@ function Invoke-WinUtilISOExport {
$sync["WPFWin11ISOChooseISOButton"].IsEnabled = $true $sync["WPFWin11ISOChooseISOButton"].IsEnabled = $true
}) })
} }
}) | Out-Null })
$script.BeginInvoke() | Out-Null $script.BeginInvoke()
} }
+23 -23
View File
@@ -84,27 +84,27 @@ function Invoke-WinUtilISOScript {
function Add-DriversToImage { function Add-DriversToImage {
param ([string]$MountPath, [string]$DriverDir, [string]$Label = "image", [scriptblock]$Logger) param ([string]$MountPath, [string]$DriverDir, [string]$Label = "image", [scriptblock]$Logger)
& dism /English "/image:$MountPath" /Add-Driver "/Driver:$DriverDir" /Recurse 2>&1 | & dism /English "/image:$MountPath" /Add-Driver "/Driver:$DriverDir" /Recurse |
ForEach-Object { & $Logger " dism[$Label]: $_" } ForEach-Object { & $Logger " dism[$Label]: $_" }
} }
function Invoke-BootWimInject { function Invoke-BootWimInject {
param ([string]$BootWimPath, [string]$DriverDir, [scriptblock]$Logger) param ([string]$BootWimPath, [string]$DriverDir, [scriptblock]$Logger)
Set-ItemProperty -Path $BootWimPath -Name IsReadOnly -Value $false -ErrorAction SilentlyContinue Set-ItemProperty -Path $BootWimPath -Name IsReadOnly -Value $false
$mountDir = Join-Path $env:TEMP "WinUtil_BootMount_$(Get-Random)" $mountDir = Join-Path $env:TEMP "WinUtil_BootMount_$(Get-Random)"
New-Item -Path $mountDir -ItemType Directory -Force | Out-Null New-Item -Path $mountDir -ItemType Directory -Force
try { try {
& $Logger "Mounting boot.wim (index 2) for driver injection..." & $Logger "Mounting boot.wim (index 2) for driver injection..."
Mount-WindowsImage -ImagePath $BootWimPath -Index 2 -Path $mountDir -ErrorAction Stop | Out-Null Mount-WindowsImage -ImagePath $BootWimPath -Index 2 -Path $mountDir
Add-DriversToImage -MountPath $mountDir -DriverDir $DriverDir -Label "boot" -Logger $Logger Add-DriversToImage -MountPath $mountDir -DriverDir $DriverDir -Label "boot" -Logger $Logger
& $Logger "Saving boot.wim..." & $Logger "Saving boot.wim..."
Dismount-WindowsImage -Path $mountDir -Save -ErrorAction Stop | Out-Null Dismount-WindowsImage -Path $mountDir -Save
& $Logger "boot.wim driver injection complete." & $Logger "boot.wim driver injection complete."
} catch { } catch {
& $Logger "Warning: boot.wim driver injection failed: $_" & $Logger "Warning: boot.wim driver injection failed: $_"
try { Dismount-WindowsImage -Path $mountDir -Discard -ErrorAction SilentlyContinue | Out-Null } catch {} try { Dismount-WindowsImage -Path $mountDir -Discard } catch {}
} finally { } finally {
Remove-Item -Path $mountDir -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path $mountDir -Recurse -Force
} }
} }
@@ -143,9 +143,9 @@ function Invoke-WinUtilISOScript {
if ($InjectCurrentSystemDrivers) { if ($InjectCurrentSystemDrivers) {
& $Log "Exporting all drivers from running system..." & $Log "Exporting all drivers from running system..."
$driverExportRoot = Join-Path $env:TEMP "WinUtil_DriverExport_$(Get-Random)" $driverExportRoot = Join-Path $env:TEMP "WinUtil_DriverExport_$(Get-Random)"
New-Item -Path $driverExportRoot -ItemType Directory -Force | Out-Null New-Item -Path $driverExportRoot -ItemType Directory -Force
try { try {
Export-WindowsDriver -Online -Destination $driverExportRoot | Out-Null Export-WindowsDriver -Online -Destination $driverExportRoot
& $Log "Injecting current system drivers into install.wim..." & $Log "Injecting current system drivers into install.wim..."
Add-DriversToImage -MountPath $ScratchDir -DriverDir $driverExportRoot -Label "install" -Logger $Log Add-DriversToImage -MountPath $ScratchDir -DriverDir $driverExportRoot -Label "install" -Logger $Log
@@ -163,7 +163,7 @@ function Invoke-WinUtilISOScript {
} catch { } catch {
& $Log "Error during driver export/injection: $_" & $Log "Error during driver export/injection: $_"
} finally { } finally {
Remove-Item -Path $driverExportRoot -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path $driverExportRoot -Recurse -Force
} }
} else { } else {
& $Log "Driver injection skipped." & $Log "Driver injection skipped."
@@ -231,7 +231,7 @@ function Invoke-WinUtilISOScript {
$absPath = $fileNode.GetAttribute("path") $absPath = $fileNode.GetAttribute("path")
$relPath = $absPath -replace '^[A-Za-z]:[/\\]', '' $relPath = $absPath -replace '^[A-Za-z]:[/\\]', ''
$destPath = Join-Path $ScratchDir $relPath $destPath = Join-Path $ScratchDir $relPath
New-Item -Path (Split-Path $destPath -Parent) -ItemType Directory -Force -ErrorAction SilentlyContinue | Out-Null New-Item -Path (Split-Path $destPath -Parent) -ItemType Directory -Force
$ext = [IO.Path]::GetExtension($destPath).ToLower() $ext = [IO.Path]::GetExtension($destPath).ToLower()
$encoding = switch ($ext) { $encoding = switch ($ext) {
@@ -326,23 +326,23 @@ function Invoke-WinUtilISOScript {
# ── 4. Delete scheduled task definition files ───────────────────────────── # ── 4. Delete scheduled task definition files ─────────────────────────────
& $Log "Deleting scheduled task definition files..." & $Log "Deleting scheduled task definition files..."
$tasksPath = "$ScratchDir\Windows\System32\Tasks" $tasksPath = "$ScratchDir\Windows\System32\Tasks"
Remove-Item "$tasksPath\Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser" -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser" -Force
Remove-Item "$tasksPath\Microsoft\Windows\Customer Experience Improvement Program" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\Customer Experience Improvement Program" -Recurse -Force
Remove-Item "$tasksPath\Microsoft\Windows\Application Experience\ProgramDataUpdater" -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\Application Experience\ProgramDataUpdater" -Force
Remove-Item "$tasksPath\Microsoft\Windows\Chkdsk\Proxy" -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\Chkdsk\Proxy" -Force
Remove-Item "$tasksPath\Microsoft\Windows\Windows Error Reporting\QueueReporting" -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\Windows Error Reporting\QueueReporting" -Force
Remove-Item "$tasksPath\Microsoft\Windows\InstallService" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\InstallService" -Recurse -Force
Remove-Item "$tasksPath\Microsoft\Windows\UpdateOrchestrator" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\UpdateOrchestrator" -Recurse -Force
Remove-Item "$tasksPath\Microsoft\Windows\UpdateAssistant" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\UpdateAssistant" -Recurse -Force
Remove-Item "$tasksPath\Microsoft\Windows\WaaSMedic" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\WaaSMedic" -Recurse -Force
Remove-Item "$tasksPath\Microsoft\Windows\WindowsUpdate" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\Windows\WindowsUpdate" -Recurse -Force
Remove-Item "$tasksPath\Microsoft\WindowsUpdate" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item "$tasksPath\Microsoft\WindowsUpdate" -Recurse -Force
& $Log "Scheduled task files deleted." & $Log "Scheduled task files deleted."
# ── 5. Remove ISO support folder ───────────────────────────────────────── # ── 5. Remove ISO support folder ─────────────────────────────────────────
if ($ISOContentsDir -and (Test-Path $ISOContentsDir)) { if ($ISOContentsDir -and (Test-Path $ISOContentsDir)) {
& $Log "Removing ISO support\ folder..." & $Log "Removing ISO support\ folder..."
Remove-Item -Path (Join-Path $ISOContentsDir "support") -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path (Join-Path $ISOContentsDir "support") -Recurse -Force
& $Log "ISO support\ folder removed." & $Log "ISO support\ folder removed."
} }
} }
+23 -23
View File
@@ -93,7 +93,7 @@ function Invoke-WinUtilISOWriteUSB {
} }
function Get-FreeDriveLetter { function Get-FreeDriveLetter {
$used = (Get-PSDrive -PSProvider FileSystem -ErrorAction SilentlyContinue).Name $used = (Get-PSDrive -PSProvider FileSystem).Name
foreach ($c in [char[]](68..90)) { foreach ($c in [char[]](68..90)) {
if ($used -notcontains [string]$c) { return $c } if ($used -notcontains [string]$c) { return $c }
} }
@@ -107,29 +107,29 @@ function Invoke-WinUtilISOWriteUSB {
$dpFile1 = Join-Path $env:TEMP "winutil_diskpart_$(Get-Random).txt" $dpFile1 = Join-Path $env:TEMP "winutil_diskpart_$(Get-Random).txt"
"select disk $diskNum`nclean`nexit" | Set-Content -Path $dpFile1 -Encoding ASCII "select disk $diskNum`nclean`nexit" | Set-Content -Path $dpFile1 -Encoding ASCII
Log "Running diskpart clean on Disk $diskNum..." Log "Running diskpart clean on Disk $diskNum..."
$dpCleanOut = diskpart /s $dpFile1 2>&1 $dpCleanOut = diskpart /s $dpFile1
$dpCleanOut | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" } $dpCleanOut | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" }
Remove-Item $dpFile1 -Force -ErrorAction SilentlyContinue Remove-Item $dpFile1 -Force
if (($dpCleanOut -join ' ') -match 'device is not ready') { if (($dpCleanOut -join ' ') -match 'device is not ready') {
Log "Disk $diskNum was not ready; waiting 5 seconds and retrying clean..." Log "Disk $diskNum was not ready; waiting 5 seconds and retrying clean..."
Start-Sleep -Seconds 5 Start-Sleep -Seconds 5
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue Update-Disk -Number $diskNum
$dpFile1b = Join-Path $env:TEMP "winutil_diskpart_$(Get-Random).txt" $dpFile1b = Join-Path $env:TEMP "winutil_diskpart_$(Get-Random).txt"
"select disk $diskNum`nclean`nexit" | Set-Content -Path $dpFile1b -Encoding ASCII "select disk $diskNum`nclean`nexit" | Set-Content -Path $dpFile1b -Encoding ASCII
diskpart /s $dpFile1b 2>&1 | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" } diskpart /s $dpFile1b | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" }
Remove-Item $dpFile1b -Force -ErrorAction SilentlyContinue Remove-Item $dpFile1b -Force
} }
# Phase 2: Initialize as GPT # Phase 2: Initialize as GPT
Start-Sleep -Seconds 2 Start-Sleep -Seconds 2
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue Update-Disk -Number $diskNum
$diskObj = Get-Disk -Number $diskNum -ErrorAction Stop $diskObj = Get-Disk -Number $diskNum
if ($diskObj.PartitionStyle -eq 'RAW') { if ($diskObj.PartitionStyle -eq 'RAW') {
Initialize-Disk -Number $diskNum -PartitionStyle GPT -ErrorAction Stop Initialize-Disk -Number $diskNum -PartitionStyle GPT
Log "Disk $diskNum initialized as GPT." Log "Disk $diskNum initialized as GPT."
} else { } else {
Set-Disk -Number $diskNum -PartitionStyle GPT -ErrorAction Stop Set-Disk -Number $diskNum -PartitionStyle GPT
Log "Disk $diskNum converted to GPT (was $($diskObj.PartitionStyle))." Log "Disk $diskNum converted to GPT (was $($diskObj.PartitionStyle))."
} }
@@ -138,7 +138,7 @@ function Invoke-WinUtilISOWriteUSB {
$volLabel = "W11-" + (Get-Date).ToString('yyMMdd') $volLabel = "W11-" + (Get-Date).ToString('yyMMdd')
$dpFile2 = Join-Path $env:TEMP "winutil_diskpart2_$(Get-Random).txt" $dpFile2 = Join-Path $env:TEMP "winutil_diskpart2_$(Get-Random).txt"
$maxFat32PartitionMB = 32768 $maxFat32PartitionMB = 32768
$diskSizeMB = [int][Math]::Floor((Get-Disk -Number $diskNum -ErrorAction Stop).Size / 1MB) $diskSizeMB = [int][Math]::Floor((Get-Disk -Number $diskNum).Size / 1MB)
$createPartitionCommand = "create partition primary" $createPartitionCommand = "create partition primary"
if ($diskSizeMB -gt $maxFat32PartitionMB) { if ($diskSizeMB -gt $maxFat32PartitionMB) {
$createPartitionCommand = "create partition primary size=$maxFat32PartitionMB" $createPartitionCommand = "create partition primary size=$maxFat32PartitionMB"
@@ -151,14 +151,14 @@ function Invoke-WinUtilISOWriteUSB {
"exit" "exit"
) | Set-Content -Path $dpFile2 -Encoding ASCII ) | Set-Content -Path $dpFile2 -Encoding ASCII
Log "Creating partitions on Disk $diskNum..." Log "Creating partitions on Disk $diskNum..."
diskpart /s $dpFile2 2>&1 | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" } diskpart /s $dpFile2 | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" }
Remove-Item $dpFile2 -Force -ErrorAction SilentlyContinue Remove-Item $dpFile2 -Force
SetProgress "Formatting USB partition..." 25 SetProgress "Formatting USB partition..." 25
Start-Sleep -Seconds 3 Start-Sleep -Seconds 3
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue Update-Disk -Number $diskNum
$partitions = Get-Partition -DiskNumber $diskNum -ErrorAction Stop $partitions = Get-Partition -DiskNumber $diskNum
Log "Partitions on Disk $diskNum after creation: $($partitions.Count)" Log "Partitions on Disk $diskNum after creation: $($partitions.Count)"
foreach ($p in $partitions) { foreach ($p in $partitions) {
Log " Partition $($p.PartitionNumber) Type=$($p.Type) Letter=$($p.DriveLetter) Size=$([math]::Round($p.Size/1MB))MB" Log " Partition $($p.PartitionNumber) Type=$($p.Type) Letter=$($p.DriveLetter) Size=$([math]::Round($p.Size/1MB))MB"
@@ -173,14 +173,14 @@ function Invoke-WinUtilISOWriteUSB {
# with 'no volume selected' when the partition has never been formatted before) # with 'no volume selected' when the partition has never been formatted before)
Log "Formatting Partition $($winpePart.PartitionNumber) as FAT32 (label: $volLabel)..." Log "Formatting Partition $($winpePart.PartitionNumber) as FAT32 (label: $volLabel)..."
Get-Partition -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber | Get-Partition -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber |
Format-Volume -FileSystem FAT32 -NewFileSystemLabel $volLabel -Force -Confirm:$false | Out-Null Format-Volume -FileSystem FAT32 -NewFileSystemLabel $volLabel -Force -Confirm:$false
Log "Partition $($winpePart.PartitionNumber) formatted as FAT32." Log "Partition $($winpePart.PartitionNumber) formatted as FAT32."
SetProgress "Assigning drive letters..." 30 SetProgress "Assigning drive letters..." 30
Start-Sleep -Seconds 2 Start-Sleep -Seconds 2
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue Update-Disk -Number $diskNum
try { Remove-PartitionAccessPath -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber -AccessPath "$($winpePart.DriveLetter):" -ErrorAction SilentlyContinue } catch {} try { Remove-PartitionAccessPath -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber -AccessPath "$($winpePart.DriveLetter):" } catch {}
$usbLetter = Get-FreeDriveLetter $usbLetter = Get-FreeDriveLetter
if (-not $usbLetter) { throw "No free drive letters (D-Z) available to assign to the USB data partition." } if (-not $usbLetter) { throw "No free drive letters (D-Z) available to assign to the USB data partition." }
Set-Partition -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber -NewDriveLetter $usbLetter Set-Partition -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber -NewDriveLetter $usbLetter
@@ -197,9 +197,9 @@ function Invoke-WinUtilISOWriteUSB {
if (-not (Test-Path $usbDrive)) { throw "Drive $usbDrive is not accessible after letter assignment." } if (-not (Test-Path $usbDrive)) { throw "Drive $usbDrive is not accessible after letter assignment." }
Log "USB data partition: $usbDrive" Log "USB data partition: $usbDrive"
$contentSizeBytes = (Get-ChildItem -LiteralPath $contentsDir -File -Recurse -Force -ErrorAction Stop | Measure-Object -Property Length -Sum).Sum $contentSizeBytes = (Get-ChildItem -LiteralPath $contentsDir -File -Recurse -Force | Measure-Object -Property Length -Sum).Sum
if (-not $contentSizeBytes) { $contentSizeBytes = 0 } if (-not $contentSizeBytes) { $contentSizeBytes = 0 }
$usbVolume = Get-Volume -DriveLetter $usbLetter -ErrorAction Stop $usbVolume = Get-Volume -DriveLetter $usbLetter
$partitionCapacityBytes = [int64]$usbVolume.Size $partitionCapacityBytes = [int64]$usbVolume.Size
$partitionFreeBytes = [int64]$usbVolume.SizeRemaining $partitionFreeBytes = [int64]$usbVolume.SizeRemaining
@@ -226,7 +226,7 @@ function Invoke-WinUtilISOWriteUSB {
if ($wimSizeMB -gt 3800) { if ($wimSizeMB -gt 3800) {
Log "install.wim is $wimSizeMB MB - splitting for FAT32 compatibility... This will take several minutes." Log "install.wim is $wimSizeMB MB - splitting for FAT32 compatibility... This will take several minutes."
$splitDest = Join-Path $usbDrive "sources\install.swm" $splitDest = Join-Path $usbDrive "sources\install.swm"
New-Item -ItemType Directory -Path (Split-Path $splitDest) -Force | Out-Null New-Item -ItemType Directory -Path (Split-Path $splitDest) -Force
Split-WindowsImage -ImagePath $installWim -SplitImagePath $splitDest -FileSize 3800 -CheckIntegrity Split-WindowsImage -ImagePath $installWim -SplitImagePath $splitDest -FileSize 3800 -CheckIntegrity
Log "install.wim split complete." Log "install.wim split complete."
Log "Copying remaining files to USB..." Log "Copying remaining files to USB..."
@@ -262,7 +262,7 @@ function Invoke-WinUtilISOWriteUSB {
$sync["WPFWin11ISOWriteUSBButton"].IsEnabled = $true $sync["WPFWin11ISOWriteUSBButton"].IsEnabled = $true
}) })
} }
}) | Out-Null })
$script.BeginInvoke() | Out-Null $script.BeginInvoke()
} }