From 1921809c3032392d6fa14a51451713b7ae414c06 Mon Sep 17 00:00:00 2001 From: MKellyCBSD <167896478+MKellyCBSD@users.noreply.github.com> Date: Wed, 15 May 2024 15:42:00 -0400 Subject: [PATCH 1/9] Update InstallAppsandSysprep.cmd Remove this command because moving it up right after updates are applied to the scratch VHDX saves ~650MB on the final .ffu file. --- FFUDevelopment/Apps/InstallAppsandSysprep.cmd | 3 --- 1 file changed, 3 deletions(-) diff --git a/FFUDevelopment/Apps/InstallAppsandSysprep.cmd b/FFUDevelopment/Apps/InstallAppsandSysprep.cmd index 1d2e97f..b617bd7 100644 --- a/FFUDevelopment/Apps/InstallAppsandSysprep.cmd +++ b/FFUDevelopment/Apps/InstallAppsandSysprep.cmd @@ -15,8 +15,5 @@ del c:\windows\panther\unattend\unattend.xml /F /Q del c:\windows\panther\unattend.xml /F /Q taskkill /IM sysprep.exe timeout /t 10 -REM Run Component Cleanup since dism /online /cleanup-image /analyzecomponentcleanup recommends it -REM If adding latest CU, definitely need to do this to keep FFU size smaller -dism /online /cleanup-image /startcomponentcleanup /resetbase REM Sysprep/Generalize c:\windows\system32\sysprep\sysprep.exe /quiet /generalize /oobe From 3f4836b47826b2fd9210f9abd42c34f54fcc2a4a Mon Sep 17 00:00:00 2001 From: MKellyCBSD <167896478+MKellyCBSD@users.noreply.github.com> Date: Wed, 15 May 2024 15:52:38 -0400 Subject: [PATCH 2/9] Update BuildFFUVM.ps1 Adding "-PreventPending" to the "add-windowspackage" command allows the dism cleanup of the winsxs folder command to be moved from the InstallAppsandSysprep.cmd script to right after the updates are added to the vhdx. The end result: FFU image size before: 11.836GB FFU image size after: 11.190GB --- FFUDevelopment/BuildFFUVM.ps1 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/FFUDevelopment/BuildFFUVM.ps1 b/FFUDevelopment/BuildFFUVM.ps1 index 7a24450..0258969 100644 --- a/FFUDevelopment/BuildFFUVM.ps1 +++ b/FFUDevelopment/BuildFFUVM.ps1 @@ -2240,10 +2240,13 @@ try { if ($UpdateLatestCU -or $UpdateLatestNet) { try { WriteLog "Adding KBs to $WindowsPartition" - Add-WindowsPackage -Path $WindowsPartition -PackagePath $KBPath | Out-Null + Add-WindowsPackage -Path $WindowsPartition -PackagePath $KBPath -PreventPending | Out-Null WriteLog "KBs added to $WindowsPartition" WriteLog "Removing $KBPath" Remove-Item -Path $KBPath -Recurse -Force | Out-Null + WriteLog "Clean Up the WinSxS Folder" + Dism /Image:$WindowsPartition /Cleanup-Image /StartComponentCleanup /ResetBase | Out-Null + WriteLog "Clean Up the WinSxS Folder completed" } catch { Write-Host "Adding KB to VHDX failed with error $_" @@ -2498,4 +2501,4 @@ If ($CleanupAppsISO) { #Clean up dirty.txt file Remove-Item -Path .\dirty.txt -Force | out-null Write-Host "Script complete" -WriteLog "Script complete" \ No newline at end of file +WriteLog "Script complete" From 49a9fd49c157e549a5dbf7a87584f339799c71f4 Mon Sep 17 00:00:00 2001 From: Zehadi Alam <63765084+zehadialam@users.noreply.github.com> Date: Mon, 20 May 2024 20:09:26 -0400 Subject: [PATCH 3/9] Add Optimize-FFUCaptureDrive function and disk cleanup to InstallAppsandSysprep.cmd file --- FFUDevelopment/Apps/InstallAppsandSysprep.cmd | 17 ++++++++++++ FFUDevelopment/BuildFFUVM.ps1 | 26 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/FFUDevelopment/Apps/InstallAppsandSysprep.cmd b/FFUDevelopment/Apps/InstallAppsandSysprep.cmd index 1d2e97f..31cf62d 100644 --- a/FFUDevelopment/Apps/InstallAppsandSysprep.cmd +++ b/FFUDevelopment/Apps/InstallAppsandSysprep.cmd @@ -18,5 +18,22 @@ timeout /t 10 REM Run Component Cleanup since dism /online /cleanup-image /analyzecomponentcleanup recommends it REM If adding latest CU, definitely need to do this to keep FFU size smaller dism /online /cleanup-image /startcomponentcleanup /resetbase +REM Run disk cleanup (cleanmgr.exe) with all options enabled: https://learn.microsoft.com/en-us/troubleshoot/windows-server/backup-and-storage/automating-disk-cleanup-tool +set rootkey=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches +REM Per above doc, the Offline Pages Files subkey does not have stateflags value +for /f "tokens=*" %%K in ('reg query "%rootkey%"') do ( + echo %%K | findstr /i /c:"Offline Pages Files" + if errorlevel 1 ( + reg add "%%K" /v StateFlags0000 /t REG_DWORD /d 2 /f + ) +) +cleanmgr.exe /sagerun:0 +REM Remove the StateFlags0000 registry value +for /f "tokens=*" %%K in ('reg query "%rootkey%"') do ( + echo %%K | findstr /i /c:"Offline Pages Files" + if errorlevel 1 ( + reg delete "%%K" /v StateFlags0000 /f + ) +) REM Sysprep/Generalize c:\windows\system32\sysprep\sysprep.exe /quiet /generalize /oobe diff --git a/FFUDevelopment/BuildFFUVM.ps1 b/FFUDevelopment/BuildFFUVM.ps1 index 7a24450..aceaa03 100644 --- a/FFUDevelopment/BuildFFUVM.ps1 +++ b/FFUDevelopment/BuildFFUVM.ps1 @@ -1438,6 +1438,31 @@ function New-PEMedia { Remove-Item -Path "$WinPEFFUPath" -Recurse -Force WriteLog 'Cleanup complete' } + +function Optimize-FFUCaptureDrive { + param ( + [string]$VhdxPath + ) + try { + WriteLog 'Mounting VHDX for volume optimization' + Mount-VHD -Path $VhdxPath + WriteLog 'Defragmenting Windows partition...' + Optimize-Volume -DriveLetter W -Defrag -NormalPriority -Verbose + WriteLog 'Performing slab consolidation on Windows partition...' + Optimize-Volume -DriveLetter W -SlabConsolidate -NormalPriority -Verbose + WriteLog 'Dismounting VHDX' + Dismount-ScratchVhdx -VhdxPath $VhdxPath + WriteLog 'Mounting VHDX as read-only for optimization' + Mount-VHD -Path $VhdxPath -NoDriveLetter -ReadOnly + WriteLog 'Optimizing VHDX in full mode...' + Optimize-VHD -Path $VhdxPath -Mode Full + WriteLog 'Dismounting VHDX' + Dismount-ScratchVhdx -VhdxPath $VhdxPath + } catch { + throw $_ + } +} + function New-FFU { param ( [Parameter(Mandatory = $false)] @@ -2364,6 +2389,7 @@ try { WriteLog 'Waiting for VM to shutdown' } while ($FFUVM.State -ne 'Off') WriteLog 'VM Shutdown' + Optimize-FFUCaptureDrive -VhdxPath $VHDXPath #Capture FFU file New-FFU $FFUVM.Name } From 12edabf213b580a3916846537a6143f49d2cb13f Mon Sep 17 00:00:00 2001 From: rbalsleyMSFT <53497092+rbalsleyMSFT@users.noreply.github.com> Date: Fri, 24 May 2024 15:29:05 -0700 Subject: [PATCH 4/9] Changed version to 2405.1 --- FFUDevelopment/BuildFFUVM.ps1 | 2 +- FFUDevelopment/WinPEDeployFFUFiles/ApplyFFU.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/FFUDevelopment/BuildFFUVM.ps1 b/FFUDevelopment/BuildFFUVM.ps1 index 23f732d..77ebbeb 100644 --- a/FFUDevelopment/BuildFFUVM.ps1 +++ b/FFUDevelopment/BuildFFUVM.ps1 @@ -283,7 +283,7 @@ param( [bool]$CleanupDeployISO = $true, [bool]$CleanupAppsISO = $true ) -$version = '2404.2' +$version = '2405.1' #Check if Hyper-V feature is installed (requires only checks the module) $osInfo = Get-WmiObject -Class Win32_OperatingSystem diff --git a/FFUDevelopment/WinPEDeployFFUFiles/ApplyFFU.ps1 b/FFUDevelopment/WinPEDeployFFUFiles/ApplyFFU.ps1 index d30d15f..ad06c3c 100644 --- a/FFUDevelopment/WinPEDeployFFUFiles/ApplyFFU.ps1 +++ b/FFUDevelopment/WinPEDeployFFUFiles/ApplyFFU.ps1 @@ -117,7 +117,7 @@ $LogFileName = 'ScriptLog.txt' $USBDrive = Get-USBDrive New-item -Path $USBDrive -Name $LogFileName -ItemType "file" -Force | Out-Null $LogFile = $USBDrive + $LogFilename -$version = '2404.3' +$version = '2405.1' WriteLog 'Begin Logging' WriteLog "Script version: $version" From 4932777f4ffb9c61c728b151a2b527e6862f2d2f Mon Sep 17 00:00:00 2001 From: rbalsleyMSFT <53497092+rbalsleyMSFT@users.noreply.github.com> Date: Fri, 24 May 2024 18:06:06 -0700 Subject: [PATCH 5/9] syntax cleanup --- FFUDevelopment/BuildFFUVM.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FFUDevelopment/BuildFFUVM.ps1 b/FFUDevelopment/BuildFFUVM.ps1 index 77ebbeb..b74b98b 100644 --- a/FFUDevelopment/BuildFFUVM.ps1 +++ b/FFUDevelopment/BuildFFUVM.ps1 @@ -2269,7 +2269,7 @@ try { WriteLog "KBs added to $WindowsPartition" WriteLog "Removing $KBPath" Remove-Item -Path $KBPath -Recurse -Force | Out-Null - WriteLog "Clean Up the WinSxS Folder" + WriteLog "Clean Up the WinSxS Folder" Dism /Image:$WindowsPartition /Cleanup-Image /StartComponentCleanup /ResetBase | Out-Null WriteLog "Clean Up the WinSxS Folder completed" } From 8f81e691595ed2a4a9b7a6f18be0f7a4ad0f9ada Mon Sep 17 00:00:00 2001 From: rbalsleyMSFT <53497092+rbalsleyMSFT@users.noreply.github.com> Date: Fri, 24 May 2024 18:12:43 -0700 Subject: [PATCH 6/9] Modify Resetbase command to use DandIEnv --- FFUDevelopment/BuildFFUVM.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FFUDevelopment/BuildFFUVM.ps1 b/FFUDevelopment/BuildFFUVM.ps1 index b74b98b..dc4a6af 100644 --- a/FFUDevelopment/BuildFFUVM.ps1 +++ b/FFUDevelopment/BuildFFUVM.ps1 @@ -2270,7 +2270,7 @@ try { WriteLog "Removing $KBPath" Remove-Item -Path $KBPath -Recurse -Force | Out-Null WriteLog "Clean Up the WinSxS Folder" - Dism /Image:$WindowsPartition /Cleanup-Image /StartComponentCleanup /ResetBase | Out-Null + Invoke-Process cmd "/c ""$DandIEnv"" && Dism /Image:$WindowsPartition /Cleanup-Image /StartComponentCleanup /ResetBase" | Out-Null WriteLog "Clean Up the WinSxS Folder completed" } catch { From d5b81bc4826e0811488c159f7125824389fef740 Mon Sep 17 00:00:00 2001 From: rbalsleyMSFT <53497092+rbalsleyMSFT@users.noreply.github.com> Date: Fri, 24 May 2024 18:18:39 -0700 Subject: [PATCH 7/9] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 0740c92..7232576 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,12 @@ This process will copy Windows in about 2-3 minutes to the target device, option While we use this in Education at Microsoft, other industries can use it as well. We esepcially see a need for something like this with partners who do re-imaging on behalf of customers. The difference in Education is that they typically have large deployments that tend to happen at the beginning of the school year and any amount of time saved is helpful. Microsoft Deployment Toolkit, Configuration Manager, and other community solutions are all great solutions, but are typically slower due to WIM deployments being file-based while FFU files are sector-based. # Updates +**2405.1** +- Moved the resetbase command from within the VM to after servicing the VHDX. This will make it so the FFU size is smaller after the latest CU or .NET framework are installed. Thanks to Mike Kelly for the PR [Commit](https://github.com/rbalsleyMSFT/FFU/pull/24) +- Some additional FFU size reduction enhancements (Thanks Zehadi Alam [Commit](https://github.com/rbalsleyMSFT/FFU/pull/25): +-- Disk cleanup is now run before sysprep to help reduce FFU file size +-- Before FFU capture, Optimize-FFU is run to defrag and slabconsolidate the VHDX + **2404.3** - Fixed an issue where the latest Windows CU wasn't downloading properly [Commit](https://github.com/rbalsleyMSFT/FFU/commit/ae59183a199f39b310c79b31c9b4980fafdeb79b) From 4d9e1c1f88813ee7292aa5112fd302f50fb1f6c9 Mon Sep 17 00:00:00 2001 From: rbalsleyMSFT <53497092+rbalsleyMSFT@users.noreply.github.com> Date: Fri, 24 May 2024 18:21:08 -0700 Subject: [PATCH 8/9] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7232576..8cfb4e1 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ While we use this in Education at Microsoft, other industries can use it as well **2405.1** - Moved the resetbase command from within the VM to after servicing the VHDX. This will make it so the FFU size is smaller after the latest CU or .NET framework are installed. Thanks to Mike Kelly for the PR [Commit](https://github.com/rbalsleyMSFT/FFU/pull/24) - Some additional FFU size reduction enhancements (Thanks Zehadi Alam [Commit](https://github.com/rbalsleyMSFT/FFU/pull/25): --- Disk cleanup is now run before sysprep to help reduce FFU file size --- Before FFU capture, Optimize-FFU is run to defrag and slabconsolidate the VHDX + - Disk cleanup is now run before sysprep to help reduce FFU file size + - Before FFU capture, Optimize-FFU is run to defrag and slabconsolidate the VHDX **2404.3** From ff46c10d79dd59f754d1e30695013f9882096069 Mon Sep 17 00:00:00 2001 From: rbalsleyMSFT <53497092+rbalsleyMSFT@users.noreply.github.com> Date: Fri, 24 May 2024 18:22:21 -0700 Subject: [PATCH 9/9] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8cfb4e1..b3c4ff8 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ While we use this in Education at Microsoft, other industries can use it as well # Updates **2405.1** -- Moved the resetbase command from within the VM to after servicing the VHDX. This will make it so the FFU size is smaller after the latest CU or .NET framework are installed. Thanks to Mike Kelly for the PR [Commit](https://github.com/rbalsleyMSFT/FFU/pull/24) -- Some additional FFU size reduction enhancements (Thanks Zehadi Alam [Commit](https://github.com/rbalsleyMSFT/FFU/pull/25): +- Moved the resetbase command from within the VM to after servicing the VHDX. This will make it so the FFU size is smaller after the latest CU or .NET framework are installed. (Thanks to Mike Kelly for the PR [Commit](https://github.com/rbalsleyMSFT/FFU/pull/24)) +- Some additional FFU size reduction enhancements (Thanks Zehadi Alam [Commit](https://github.com/rbalsleyMSFT/FFU/pull/25)): - Disk cleanup is now run before sysprep to help reduce FFU file size - Before FFU capture, Optimize-FFU is run to defrag and slabconsolidate the VHDX