1
0

nano11 builder script refinement

Some artifacts such as cursors, webview components etc. are
not being removed during builds, leading to increased ISO sizes.

Clean up scratch directory handling and code structure in an attempt
to find the cause.

Signed-off-by: Stefan Knoblich <stkn@bitplumber.de>
This commit is contained in:
2026-05-24 20:59:38 +02:00
parent dc814ff379
commit d512416270
+116 -63
View File
@@ -69,7 +69,34 @@ function Set-ItemOwnershipAndAccess {
} }
} }
Start-Transcript -Path "$PSScriptRoot\nano11.log" function Set-RegistryValue {
param (
[string]$path,
[string]$name,
[string]$type,
[string]$value
)
try {
& 'reg' 'add' $path '/v' $name '/t' $type '/d' $value '/f' | Out-Null
Write-Output "Set registry value: $path\$name"
} catch {
Write-Output "Error setting registry value: $_"
}
}
function Remove-RegistryValue {
param (
[string]$path
)
try {
& 'reg' 'delete' $path '/f' | Out-Null
Write-Output "Removed registry value: $path"
} catch {
Write-Output "Error removing registry value: $_"
}
}
Start-Transcript -Path "$PSScriptRoot\nano11-$(Get-Date -f yyyyMMdd_HHmmss).log"
# User prompt (accepts y/n) # User prompt (accepts y/n)
Write-Host "Welcome to the nano11 Builder!" Write-Host "Welcome to the nano11 Builder!"
Write-Host "This script generates a heavily reduced Windows 11 image. It's not intended for regular use as it cannot be serviced (no updates, languages, etc.)." Write-Host "This script generates a heavily reduced Windows 11 image. It's not intended for regular use as it cannot be serviced (no updates, languages, etc.)."
@@ -85,14 +112,14 @@ Write-Host "Off we go..."
Start-Sleep -Seconds 3 Start-Sleep -Seconds 3
Clear-Host Clear-Host
$mainOSDrive = $env:SystemDrive
if (-not $SCRATCH) { if (-not $SCRATCH) {
$ScratchDisk = $env:SystemDrive $scratchDrive = $mainOSDrive
} else { } else {
$ScratchDisk = $SCRATCH + ":" $scratchDrive = $SCRATCH + ":"
} }
$mainOSDrive = $env:SystemDrive New-Item -ItemType Directory -Force -Path "$scratchDrive\nano11\sources"
New-Item -ItemType Directory -Force -Path "$mainOSDrive\nano11\sources"
do { do {
if (-not $ISO) { if (-not $ISO) {
@@ -114,7 +141,7 @@ if (-not (Test-Path "$DriveLetter\sources\install.wim")) {
& 'dism' /English /Get-WimInfo /WimFile:"$DriveLetter\sources\install.esd" & 'dism' /English /Get-WimInfo /WimFile:"$DriveLetter\sources\install.esd"
$index = Read-Host "Please enter the image index" $index = Read-Host "Please enter the image index"
Write-Host 'Converting install.esd to install.wim. This may take a while...' Write-Host 'Converting install.esd to install.wim. This may take a while...'
& 'dism' /English /Export-Image /SourceImageFile:"$DriveLetter\sources\install.esd" /SourceIndex:$index /DestinationImageFile:"$mainOSDrive\nano11\sources\install.wim" /Compress:max /CheckIntegrity & 'dism' /English /Export-Image /SourceImageFile:"$DriveLetter\sources\install.esd" /SourceIndex:$index /DestinationImageFile:"$scratchDrive\nano11\sources\install.wim" /Compress:max /CheckIntegrity
} else { } else {
Write-Host "No Windows installation files found on the specified drive. Exiting." Write-Host "No Windows installation files found on the specified drive. Exiting."
exit exit
@@ -124,11 +151,11 @@ if (-not (Test-Path "$DriveLetter\sources\install.wim")) {
} }
Write-Host "Copying Windows image..." Write-Host "Copying Windows image..."
Copy-Item -Path "$DriveLetter\*" -Destination "$mainOSDrive\nano11" -Recurse -Force > $null Copy-Item -Path "$DriveLetter\*" -Destination "$scratchDrive\nano11" -Recurse -Force | Out-Null
Remove-Item "$mainOSDrive\nano11\sources\install.esd" -ErrorAction SilentlyContinue Remove-Item "$scratchDrive\nano11\sources\install.esd" -ErrorAction SilentlyContinue
Write-Host "Getting image information:" Write-Host "Getting image information:"
$wimFilePath = "$mainOSDrive\nano11\sources\install.wim" $wimFilePath = "$scratchDrive\nano11\sources\install.wim"
$ImagesIndex = (Get-WindowsImage -ImagePath $wimFilePath).ImageIndex $ImagesIndex = (Get-WindowsImage -ImagePath $wimFilePath).ImageIndex
while ($ImagesIndex -notcontains $index) { while ($ImagesIndex -notcontains $index) {
Get-WindowsImage -ImagePath $wimFilePath Get-WindowsImage -ImagePath $wimFilePath
@@ -139,11 +166,11 @@ Write-Host "Mounting Windows image. This may take a while."
Set-ItemOwnershipAndAccess -Path $wimFilePath Set-ItemOwnershipAndAccess -Path $wimFilePath
try { Set-ItemProperty -Path $wimFilePath -Name IsReadOnly -Value $false -ErrorAction Stop } catch {} try { Set-ItemProperty -Path $wimFilePath -Name IsReadOnly -Value $false -ErrorAction Stop } catch {}
New-Item -ItemType Directory -Force -Path "$mainOSDrive\scratchdir" $scratchDir = "$scratchDrive\scratchdir"
Mount-WindowsImage -ImagePath "$wimFilePath" -Index $index -Path "$mainOSDrive\scratchdir" New-Item -ItemType Directory -Force -Path "$scratchDir"
Mount-WindowsImage -ImagePath "$wimFilePath" -Index $index -Path "$scratchDir"
# --- Taking ownership with the language-independent function --- # --- Taking ownership with the language-independent function ---
$scratchDir = "$mainOSDrive\scratchdir"
$foldersToOwn = @( $foldersToOwn = @(
"$scratchDir\Windows\System32\DriverStore\FileRepository", "$scratchDir\Windows\System32\DriverStore\FileRepository",
"$scratchDir\Windows\Fonts", "$scratchDir\Windows\Fonts",
@@ -165,8 +192,12 @@ $filesToOwn = @(
"$scratchDir\Windows\System32\OneDriveSetup.exe" "$scratchDir\Windows\System32\OneDriveSetup.exe"
) )
foreach ($folder in $foldersToOwn) { Set-ItemOwnershipAndAccess -Path $folder -Recurse } foreach ($folder in $foldersToOwn) {
foreach ($file in $filesToOwn) { Set-ItemOwnershipAndAccess -Path $file } Set-ItemOwnershipAndAccess -Path "$folder" -Recurse
}
foreach ($file in $filesToOwn) {
Set-ItemOwnershipAndAccess -Path "$file"
}
$imageIntl = & dism /English /Get-Intl "/Image:$scratchDir" $imageIntl = & dism /English /Get-Intl "/Image:$scratchDir"
$languageLine = $imageIntl -split '\n' | Where-Object { $_ -match 'Default system UI language : ([a-zA-Z]{2}-[a-zA-Z]{2})' } $languageLine = $imageIntl -split '\n' | Where-Object { $_ -match 'Default system UI language : ([a-zA-Z]{2}-[a-zA-Z]{2})' }
@@ -244,14 +275,14 @@ $packagePatterns = @(
"Microsoft-Media-MPEG2-Decoder-Package~", "Microsoft-Media-MPEG2-Decoder-Package~",
"Microsoft-Windows-Wallpaper-Content-Extended-FoD-Package~" "Microsoft-Windows-Wallpaper-Content-Extended-FoD-Package~"
) )
$allPackages = & dism /English /image:$scratchDir /Get-Packages /Format:Table $allPackages = & 'dism' /English /image:$scratchDir /Get-Packages /Format:Table
$allPackages = $allPackages -split "`n" | Select-Object -Skip 1 $allPackages = $allPackages -split "`n" | Select-Object -Skip 1
foreach ($packagePattern in $packagePatterns) { foreach ($packagePattern in $packagePatterns) {
$packagesToRemove = $allPackages | Where-Object { $_ -like "$packagePattern*" } $packagesToRemove = $allPackages | Where-Object { $_ -like "$packagePattern*" }
foreach ($package in $packagesToRemove) { foreach ($package in $packagesToRemove) {
$packageIdentity = ($package -split "\s+")[0] $packageIdentity = ($package -split "\s+")[0]
Write-Host "Removing $packageIdentity..." Write-Host "Removing $packageIdentity..."
& dism /English /image:$scratchDir /Remove-Package /PackageName:$packageIdentity & 'dism' /English /image:$scratchDir /Remove-Package /PackageName:$packageIdentity
} }
} }
@@ -262,18 +293,18 @@ Write-Host "Performing aggressive manual file deletions..."
$winDir = "$scratchDir\Windows" $winDir = "$scratchDir\Windows"
Write-Host "Slimming the DriverStore... (removing non-essential driver classes)" Write-Host "Slimming the DriverStore... (removing non-essential driver classes)"
$driverRepo = Join-Path -Path $winDir -ChildPath "System32\DriverStore\FileRepository" $driverRepo = Join-Path -Path "$winDir" -ChildPath "System32\DriverStore\FileRepository"
$patternsToRemove = @('prn*', 'scan*', 'mfd*', 'wscsmd.inf*', 'tapdrv*', 'rdpbus.inf*', 'tdibth.inf*') $patternsToRemove = @('prn*', 'scan*', 'mfd*', 'wscsmd.inf*', 'tapdrv*', 'rdpbus.inf*', 'tdibth.inf*')
# FIX: Use a robust deletion method for protected driver folders. # FIX: Use a robust deletion method for protected driver folders.
$emptyDirForDrivers = Join-Path -Path $scratchDir -ChildPath "empty_drivers_delete" $emptyDirForDrivers = Join-Path -Path "$scratchDir" -ChildPath "empty_drivers_delete"
New-Item -Path $emptyDirForDrivers -ItemType Directory -Force | Out-Null New-Item -Path "$emptyDirForDrivers" -ItemType Directory -Force | Out-Null
Get-ChildItem -Path $driverRepo -Directory | ForEach-Object { Get-ChildItem -Path "$driverRepo" -Directory | ForEach-Object {
$driverFolder = $_ $driverFolder = $_
foreach ($pattern in $patternsToRemove) { foreach ($pattern in $patternsToRemove) {
if ($driverFolder.Name -like $pattern) { if ($driverFolder.Name -like $pattern) {
Write-Host "Force-removing non-essential driver package: $($driverFolder.Name)" Write-Host "Force-removing non-essential driver package: $($driverFolder.Name)"
Set-ItemOwnershipAndAccess -Path $driverFolder.FullName -Recurse Set-ItemOwnershipAndAccess -Path $driverFolder.FullName -Recurse
& robocopy $emptyDirForDrivers $driverFolder.FullName /MIR /R:0 /W:0 | Out-Null & 'robocopy' "$emptyDirForDrivers" $driverFolder.FullName /MIR /R:0 /W:0 | Out-Null
Remove-Item -Path $driverFolder.FullName -Recurse -Force Remove-Item -Path $driverFolder.FullName -Recurse -Force
break break
} }
@@ -281,12 +312,12 @@ Get-ChildItem -Path $driverRepo -Directory | ForEach-Object {
} }
Remove-Item -Path $emptyDirForDrivers -Recurse -Force Remove-Item -Path $emptyDirForDrivers -Recurse -Force
$fontsPath = Join-Path -Path $winDir -ChildPath "Fonts" $fontsPath = Join-Path -Path "$winDir" -ChildPath "Fonts"
if (Test-Path $fontsPath) { if (Test-Path "$fontsPath") {
Write-Host "Slimming the Fonts folder..." Write-Host "Slimming the Fonts folder..."
# FIX: Take ownership of each font file individually before attempting to delete it. # FIX: Take ownership of each font file individually before attempting to delete it.
$fontsToRemoveExclude = Get-ChildItem -Path $fontsPath -Exclude "segoe*.*", "tahoma*.*", "marlett.ttf", "8541oem.fon", "segui*.*", "consol*.*", "lucon*.*", "calibri*.*", "arial*.*", "times*.*", "cou*.*", "8*.*" $fontsToRemoveExclude = Get-ChildItem -Path "$fontsPath" -Exclude "segoe*.*", "tahoma*.*", "marlett.ttf", "8541oem.fon", "segui*.*", "consol*.*", "lucon*.*", "calibri*.*", "arial*.*", "times*.*", "cou*.*", "8*.*"
$fontsToRemoveInclude = Get-ChildItem -Path $fontsPath -Include "mingli*", "msjh*", "msyh*", "malgun*", "meiryo*", "yugoth*", "segoeuihistoric.ttf" $fontsToRemoveInclude = Get-ChildItem -Path "$fontsPath" -Include "mingli*", "msjh*", "msyh*", "malgun*", "meiryo*", "yugoth*", "segoeuihistoric.ttf"
($fontsToRemoveExclude + $fontsToRemoveInclude) | ForEach-Object { ($fontsToRemoveExclude + $fontsToRemoveInclude) | ForEach-Object {
Write-Host " - Removing font: $($_.Name)" Write-Host " - Removing font: $($_.Name)"
Set-ItemOwnershipAndAccess -Path $_.FullName Set-ItemOwnershipAndAccess -Path $_.FullName
@@ -294,16 +325,16 @@ if (Test-Path $fontsPath) {
} }
} }
Remove-Item -Path (Join-Path -Path $winDir -ChildPath "Speech\Engines\TTS") -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path (Join-Path -Path "$winDir" -ChildPath "Speech\Engines\TTS") -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path "$scratchDir\ProgramData\Microsoft\Windows Defender\Definition Updates" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path "$scratchDir\ProgramData\Microsoft\Windows Defender\Definition Updates" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path "$scratchDir\Windows\System32\InputMethod\CHS" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path "$scratchDir\Windows\System32\InputMethod\CHS" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path "$scratchDir\Windows\System32\InputMethod\CHT" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path "$scratchDir\Windows\System32\InputMethod\CHT" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path "$scratchDir\Windows\System32\InputMethod\JPN" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path "$scratchDir\Windows\System32\InputMethod\JPN" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path "$scratchDir\Windows\System32\InputMethod\KOR" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path "$scratchDir\Windows\System32\InputMethod\KOR" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path "$scratchDir\Windows\Temp\*" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path "$scratchDir\Windows\Temp\*" -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path (Join-Path -Path $winDir -ChildPath "Web") -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path (Join-Path -Path "$winDir" -ChildPath "Web") -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path (Join-Path -Path $winDir -ChildPath "Help") -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path (Join-Path -Path "$winDir" -ChildPath "Help") -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item -Path (Join-Path -Path $winDir -ChildPath "Cursors") -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path (Join-Path -Path "$winDir" -ChildPath "Cursors") -Recurse -Force -ErrorAction SilentlyContinue
Write-Host "Removing Edge, WinRE, and OneDrive..." Write-Host "Removing Edge, WinRE, and OneDrive..."
Remove-Item -Path "$scratchDir\Program Files (x86)\Microsoft\Edge*" -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path "$scratchDir\Program Files (x86)\Microsoft\Edge*" -Recurse -Force -ErrorAction SilentlyContinue
@@ -312,15 +343,15 @@ Remove-Item -Path "$scratchDir\Program Files (x86)\Microsoft\Edge*" -Recurse -Fo
if ($architecture -eq 'amd64') { if ($architecture -eq 'amd64') {
$folderPaths = Get-ChildItem -Path "$scratchDir\Windows\WinSxS" -Filter "amd64_microsoft-edge-webview_31bf3856ad364e35*" -Directory $folderPaths = Get-ChildItem -Path "$scratchDir\Windows\WinSxS" -Filter "amd64_microsoft-edge-webview_31bf3856ad364e35*" -Directory
if ($folderPaths) { if ($folderPaths) {
$emptyDirForEdge = Join-Path -Path $scratchDir -ChildPath "empty_edge_delete" $emptyDirForEdge = Join-Path -Path "$scratchDir" -ChildPath "empty_edge_delete"
New-Item -Path $emptyDirForEdge -ItemType Directory -Force | Out-Null New-Item -Path "$emptyDirForEdge" -ItemType Directory -Force | Out-Null
foreach ($folder in $folderPaths) { foreach ($folder in $folderPaths) {
Write-Host "Force-deleting Edge WebView folder: $($folder.FullName)" Write-Host "Force-deleting Edge WebView folder: $($folder.FullName)"
Set-ItemOwnershipAndAccess -Path $folder.FullName -Recurse Set-ItemOwnershipAndAccess -Path $folder.FullName -Recurse
& robocopy $emptyDirForEdge $folder.FullName /MIR /R:0 /W:0 | Out-Null & 'robocopy' "$emptyDirForEdge" $folder.FullName /MIR /R:0 /W:0 | Out-Null
Remove-Item -Path $folder.FullName -Recurse -Force Remove-Item -Path $folder.FullName -Recurse -Force
} }
Remove-Item -Path $emptyDirForEdge -Recurse -Force Remove-Item -Path "$emptyDirForEdge" -Recurse -Force
} }
} }
@@ -335,10 +366,10 @@ Write-Host "Taking ownership of the WinSxS folder. This might take a while..."
Set-ItemOwnershipAndAccess -Path "$scratchDir\Windows\WinSxS" -Recurse Set-ItemOwnershipAndAccess -Path "$scratchDir\Windows\WinSxS" -Recurse
Write-host "Complete!" Write-host "Complete!"
$folderPath = Join-Path -Path $mainOSDrive -ChildPath "\scratchdir\Windows\WinSxS_edit" $folderPath = Join-Path -Path $scratchDrive -ChildPath "\scratchdir\Windows\WinSxS_edit"
$sourceDirectory = "$mainOSDrive\scratchdir\Windows\WinSxS" $sourceDirectory = "$scratchDrive\scratchdir\Windows\WinSxS"
$destinationDirectory = "$mainOSDrive\scratchdir\Windows\WinSxS_edit" $destinationDirectory = "$scratchDrive\scratchdir\Windows\WinSxS_edit"
New-Item -Path $folderPath -ItemType Directory New-Item -Path "$folderPath" -ItemType Directory
$dirsToCopy = @() $dirsToCopy = @()
if ($architecture -eq "amd64") { if ($architecture -eq "amd64") {
@@ -403,24 +434,24 @@ if ($architecture -eq "amd64") {
) )
} }
foreach ($dir in $dirsToCopy) { foreach ($dir in $dirsToCopy) {
$sourceDirs = Get-ChildItem -Path $sourceDirectory -Filter $dir -Directory $sourceDirs = Get-ChildItem -Path "$sourceDirectory" -Filter "$dir" -Directory
foreach ($sourceDir in $sourceDirs) { foreach ($sourceDir in $sourceDirs) {
$destDir = Join-Path -Path $destinationDirectory -ChildPath $sourceDir.Name $destDir = Join-Path -Path "$destinationDirectory" -ChildPath $sourceDir.Name
Write-Host "Copying $($sourceDir.FullName) to $destDir" Write-Host "Copying $($sourceDir.FullName) to $destDir"
Copy-Item -Path $sourceDir.FullName -Destination $destDir -Recurse -Force Copy-Item -Path $sourceDir.FullName -Destination "$destDir" -Recurse -Force
} }
} }
Write-Host "Deleting WinSxS. This may take a while..." Write-Host "Deleting WinSxS. This may take a while..."
# FIX: Use robocopy to reliably delete the protected WinSxS folder contents. # FIX: Use robocopy to reliably delete the protected WinSxS folder contents.
# Remove-Item can fail with "Access Denied" due to TrustedInstaller permissions. # Remove-Item can fail with "Access Denied" due to TrustedInstaller permissions.
$emptyDir = Join-Path -Path $scratchDir -ChildPath "empty_temp_for_delete" $emptyDir = Join-Path -Path "$scratchDir" -ChildPath "empty_temp_for_delete"
New-Item -Path $emptyDir -ItemType Directory -Force | Out-Null New-Item -Path "$emptyDir" -ItemType Directory -Force | Out-Null
& robocopy $emptyDir "$mainOSDrive\scratchdir\Windows\WinSxS" /MIR /R:0 /W:0 | Out-Null & 'robocopy' "$emptyDir" "$scratchDir\Windows\WinSxS" /MIR /R:0 /W:0 | Out-Null
Remove-Item -Path "$mainOSDrive\scratchdir\Windows\WinSxS" -Recurse -Force Remove-Item -Path "$scratchDir\Windows\WinSxS" -Recurse -Force
Remove-Item -Path $emptyDir -Recurse -Force Remove-Item -Path "$emptyDir" -Recurse -Force
Rename-Item -Path "$mainOSDrive\scratchdir\Windows\WinSxS_edit" -NewName "$mainOSDrive\scratchdir\Windows\WinSxS" Rename-Item -Path "$scratchDir\Windows\WinSxS_edit" -NewName "$scratchDir\Windows\WinSxS"
Write-Host "Complete!" Write-Host "Complete!"
reg load HKLM\zCOMPONENTS "$scratchDir\Windows\System32\config\COMPONENTS" | Out-Null reg load HKLM\zCOMPONENTS "$scratchDir\Windows\System32\config\COMPONENTS" | Out-Null
@@ -456,23 +487,41 @@ reg unload HKLM\zSYSTEM | Out-Null
Write-Host "Loading registry hives to remove services..." Write-Host "Loading registry hives to remove services..."
reg load HKLM\zSYSTEM "$scratchDir\Windows\System32\config\SYSTEM" | Out-Null reg load HKLM\zSYSTEM "$scratchDir\Windows\System32\config\SYSTEM" | Out-Null
$servicesToRemove = @('Spooler', 'PrintNotify', 'Fax', 'RemoteRegistry', 'diagsvc', 'WerSvc', 'PcaSvc', 'MapsBroker', 'WalletService', 'BthAvctpSvc', 'BluetoothUserService', 'wuauserv', 'UsoSvc', 'WaaSMedicSvc') $servicesToRemove = @(
foreach ($service in $servicesToRemove) { Write-Host "Removing service: $service"; & 'reg' 'delete' "HKLM\zSYSTEM\ControlSet001\Services\$service" /f | Out-Null } 'Spooler',
'PrintNotify',
'Fax',
'RemoteRegistry',
'diagsvc',
'WerSvc',
'PcaSvc',
'MapsBroker',
'WalletService',
'BthAvctpSvc',
'BluetoothUserService',
'wuauserv',
'UsoSvc',
'WaaSMedicSvc'
)
foreach ($service in $servicesToRemove) {
Write-Host "Removing service: $service"
& 'reg' 'delete' "HKLM\zSYSTEM\ControlSet001\Services\$service" /f | Out-Null
}
reg unload HKLM\zSYSTEM | Out-Null reg unload HKLM\zSYSTEM | Out-Null
Write-Host "Cleaning up and unmounting install.wim..." Write-Host "Cleaning up and unmounting install.wim..."
& 'dism' /English "/image:$scratchDir" /Cleanup-Image /StartComponentCleanup /ResetBase & 'dism' /English "/image:$scratchDir" /Cleanup-Image /StartComponentCleanup /ResetBase
& 'dism' /English /Unmount-Image "/mountdir:$scratchDir" /commit & 'dism' /English /Unmount-Image "/mountdir:$scratchDir" /commit
& 'dism' /English /Export-Image "/SourceImageFile:$wimFilePath" "/SourceIndex:$index" "/DestinationImageFile:$mainOSDrive\nano11\sources\install2.wim" /compress:max & 'dism' /English /Export-Image "/SourceImageFile:$wimFilePath" "/SourceIndex:$index" "/DestinationImageFile:$scratchDrive\nano11\sources\install2.wim" /compress:max
Remove-Item -Path $wimFilePath -Force Remove-Item -Path "$wimFilePath" -Force
Rename-Item -Path "$mainOSDrive\nano11\sources\install2.wim" -NewName "install.wim" Rename-Item -Path "$scratchDrive\nano11\sources\install2.wim" -NewName "install.wim"
Write-Host "Shrinking boot.wim..." Write-Host "Shrinking boot.wim..."
$bootWimPath = "$mainOSDrive\nano11\sources\boot.wim" $bootWimPath = "$scratchDrive\nano11\sources\boot.wim"
Set-ItemOwnershipAndAccess -Path $bootWimPath Set-ItemOwnershipAndAccess -Path $bootWimPath
try { Set-ItemProperty -Path $bootWimPath -Name IsReadOnly -Value $false -ErrorAction Stop } catch {} try { Set-ItemProperty -Path $bootWimPath -Name IsReadOnly -Value $false -ErrorAction Stop } catch {}
$newBootWimPath = "$mainOSDrive\nano11\sources\boot_new.wim" $newBootWimPath = "$scratchDrive\nano11\sources\boot_new.wim"
& 'dism' /English /Export-Image "/SourceImageFile:$bootWimPath" /SourceIndex:2 "/DestinationImageFile:$newBootWimPath" & 'dism' /English /Export-Image "/SourceImageFile:$bootWimPath" /SourceIndex:2 "/DestinationImageFile:$newBootWimPath"
& 'dism' /English /Mount-Image "/imagefile:$newBootWimPath" /index:1 "/mountdir:$scratchDir" & 'dism' /English /Mount-Image "/imagefile:$newBootWimPath" /index:1 "/mountdir:$scratchDir"
@@ -488,7 +537,7 @@ reg unload HKLM\zSYSTEM | Out-Null
& 'dism' /English /Unmount-Image "/mountdir:$scratchDir" /commit & 'dism' /English /Unmount-Image "/mountdir:$scratchDir" /commit
$finalBootWimPath = "$mainOSDrive\nano11\sources\boot_final.wim" $finalBootWimPath = "$scratchDrive\nano11\sources\boot_final.wim"
Remove-Item -Path $bootWimPath -Force Remove-Item -Path $bootWimPath -Force
& 'dism' /English /Export-Image "/SourceImageFile:$newBootWimPath" /SourceIndex:1 "/DestinationImageFile:$finalBootWimPath" /compress:max & 'dism' /English /Export-Image "/SourceImageFile:$newBootWimPath" /SourceIndex:1 "/DestinationImageFile:$finalBootWimPath" /compress:max
Remove-Item -Path $newBootWimPath -Force Remove-Item -Path $newBootWimPath -Force
@@ -496,13 +545,16 @@ Rename-Item -Path $finalBootWimPath -NewName "boot.wim"
Clear-Host Clear-Host
Write-Host "Exporting final image to highly compressed ESD format..." Write-Host "Exporting final image to highly compressed ESD format..."
& dism /English /Export-Image /SourceImageFile:"$mainOSdrive\nano11\sources\install.wim" /SourceIndex:1 /DestinationImageFile:"$mainOSdrive\nano11\sources\install.esd" /Compress:recovery & dism /English /Export-Image /SourceImageFile:"$scratchDrive\nano11\sources\install.wim" /SourceIndex:1 /DestinationImageFile:"$scratchDrive\nano11\sources\install.esd" /Compress:recovery
Remove-Item "$mainOSdrive\nano11\sources\install.wim" -Force -ErrorAction SilentlyContinue Remove-Item "$scratchDrive\nano11\sources\install.wim" -Force -ErrorAction SilentlyContinue
Write-Host "Performing final cleanup of installation folder root..." Write-Host "Performing final cleanup of installation folder root..."
$isoRoot = "$mainOSDrive\nano11" $isoRoot = "$scratchDrive\nano11"
$keepList = @("boot", "efi", "sources", "bootmgr", "bootmgr.efi", "setup.exe") $keepList = @("boot", "efi", "sources", "bootmgr", "bootmgr.efi", "setup.exe")
Get-ChildItem -Path $isoRoot | Where-Object { $_.Name -notin $keepList } | ForEach-Object { Write-Host "Removing non-essential file/folder from ISO root: $($_.Name)"; Remove-Item -Path $_.FullName -Recurse -Force } Get-ChildItem -Path $isoRoot | Where-Object { $_.Name -notin $keepList } | ForEach-Object {
Write-Host "Removing non-essential file/folder from ISO root: $($_.Name)"
Remove-Item -Path $_.FullName -Recurse -Force
}
Write-Host "Creating bootable ISO image..." Write-Host "Creating bootable ISO image..."
$OSCDIMG = "$PSScriptRoot\oscdimg.exe" $OSCDIMG = "$PSScriptRoot\oscdimg.exe"
@@ -511,13 +563,14 @@ if (-not (Test-Path $OSCDIMG)) {
Invoke-WebRequest -Uri $url -OutFile $OSCDIMG Invoke-WebRequest -Uri $url -OutFile $OSCDIMG
} }
& "$OSCDIMG" -m -o -u2 -udfver102 "-bootdata:2#p0,e,b$mainOSdrive\nano11\boot\etfsboot.com#pEF,e,b$mainOSdrive\nano11\efi\microsoft\boot\efisys_noprompt.bin" ` & "$OSCDIMG" -m -o -u2 -udfver102 "-bootdata:2#p0,e,b$scratchDrive\nano11\boot\etfsboot.com#pEF,e,b$scratchDrive\nano11\efi\microsoft\boot\efisys_noprompt.bin" `
"$mainOSdrive\nano11" "$PSScriptRoot\nano11.iso" "$scratchDrive\nano11" "$PSScriptRoot\nano11.iso"
Write-Host "Creation complete! Your ISO is named nano11.iso" Write-Host "Creation complete! Your ISO is named nano11.iso"
Read-Host "Press Enter to clean up and exit." Read-Host "Press Enter to clean up and exit."
& 'dism' /English /Unmount-Image /MountDir:$scratchDir /discard -ErrorAction SilentlyContinue Start-Process 'dism.exe' -ArgumentList @( '/English', '/Unmount-Image', "/MountDir:$scratchDir", '/discard' ) `
Remove-Item -Path "$mainOSdrive\nano11" -Recurse -Force -Wait -PassThru -ErrorAction SilentlyContinue
Remove-Item -Path "$mainOSdrive\scratchdir" -Recurse -Force Remove-Item -Path "$scratchDrive\nano11" -Recurse -Force
Remove-Item -Path "$scratchDrive\scratchdir" -Recurse -Force
Stop-Transcript Stop-Transcript
exit exit