mirror of
https://github.com/rbalsleyMSFT/FFU.git
synced 2026-06-14 02:09:35 -06:00
- If not passing an ISO, hardcoded WindowsVersion of 22H2 for Windows 10 or 24H2 for Windows 11 since the ESD media only provides those two versions. Not doing this allowed for unnecessary VHDX creation since it checks the WindowsVersion via the json file. This also fixes an issue where CUs could be searched for that didn’t exist, but the media would still download
- Added some additional logging entries - Removed verbose output of the Optimize-Volume command - Fixed an issue where not passing an ISO caused the script to fail - Cleaned up the KBPath folder at the end of the run - Changed some minor formatting items
This commit is contained in:
@@ -3900,6 +3900,17 @@ if (($WindowsArch -eq 'ARM64') -and ($UpdateLatestMSRT -eq $true)) {
|
|||||||
$UpdateLatestMSRT = $false
|
$UpdateLatestMSRT = $false
|
||||||
WriteLog 'Windows Malicious Software Removal Tool is not available for the ARM64 architecture.'
|
WriteLog 'Windows Malicious Software Removal Tool is not available for the ARM64 architecture.'
|
||||||
}
|
}
|
||||||
|
#If downloading ESD from MCT, hardcode WindowsVersion to 22H2 for Windows 10 and 24H2 for Windows 11
|
||||||
|
#MCT media only provides 22H2 and 24H2 media
|
||||||
|
#This prevents issues with VHDX Caching unecessarily and with searching for CUs
|
||||||
|
if ($ISOPath -eq '') {
|
||||||
|
if ($WindowsRelease -eq '10') {
|
||||||
|
$WindowsVersion = '22H2'
|
||||||
|
}
|
||||||
|
if ($WindowsRelease -eq '11') {
|
||||||
|
$WindowsVersion = '24H2'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
###END PARAMETER VALIDATION
|
###END PARAMETER VALIDATION
|
||||||
|
|
||||||
@@ -4208,7 +4219,7 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#Update Latest Preview Cumlative Update for Client OS only
|
#Update Latest Preview Cumlative Update for Client OS only
|
||||||
#will take Precendence over $UpdateLastestCU if both were set to $true
|
#will take Precendence over $UpdateLatestCU if both were set to $true
|
||||||
if ($UpdatePreviewCU -and $installationType -eq 'Client') {
|
if ($UpdatePreviewCU -and $installationType -eq 'Client') {
|
||||||
Writelog "`$UpdatePreviewCU is set to true, checking for latest Preview CU"
|
Writelog "`$UpdatePreviewCU is set to true, checking for latest Preview CU"
|
||||||
$Name = """Cumulative update Preview for Windows $WindowsRelease Version $WindowsVersion for $WindowsArch"""
|
$Name = """Cumulative update Preview for Windows $WindowsRelease Version $WindowsVersion for $WindowsArch"""
|
||||||
@@ -4262,37 +4273,41 @@ try {
|
|||||||
|
|
||||||
#Search for cached VHDX and skip VHDX creation if there's a cached version
|
#Search for cached VHDX and skip VHDX creation if there's a cached version
|
||||||
if ($AllowVHDXCaching) {
|
if ($AllowVHDXCaching) {
|
||||||
|
WriteLog 'AllowVHDXCaching is true, checking for cached VHDX file'
|
||||||
if (Test-Path -Path $VHDXCacheFolder) {
|
if (Test-Path -Path $VHDXCacheFolder) {
|
||||||
$vhdxJsons = @(Get-ChildItem -File -Path $VHDXCacheFolder -Filter "*_config.json" | Sort-Object -Property CreationTime -Descending)
|
WriteLog "Found $VHDXCacheFolder"
|
||||||
|
$vhdxJsons = @(Get-ChildItem -File -Path $VHDXCacheFolder -Filter '*_config.json' | Sort-Object -Property CreationTime -Descending)
|
||||||
|
WriteLog "Found $($vhdxJsons.Count) cached VHDX files"
|
||||||
$downloadedKBs = @(Get-ChildItem -File -Path $KBPath)
|
$downloadedKBs = @(Get-ChildItem -File -Path $KBPath)
|
||||||
#$jsonDeserializer = [System.Web.Script.Serialization.JavaScriptSerializer]::new()
|
#$jsonDeserializer = [System.Web.Script.Serialization.JavaScriptSerializer]::new()
|
||||||
|
|
||||||
foreach ($vhdxJson in $vhdxJsons) {
|
foreach ($vhdxJson in $vhdxJsons) {
|
||||||
try {
|
try {
|
||||||
|
WriteLog "Processing $($vhdxJson.FullName)"
|
||||||
#$vhdxCacheItem = $jsonDeserializer.Deserialize((Get-Content -Path $vhdxJson.FullName -Raw), [VhdxCacheItem])
|
#$vhdxCacheItem = $jsonDeserializer.Deserialize((Get-Content -Path $vhdxJson.FullName -Raw), [VhdxCacheItem])
|
||||||
$vhdxCacheItem = Get-Content -Path $vhdxJson.FullName -Raw | ConvertFrom-Json
|
$vhdxCacheItem = Get-Content -Path $vhdxJson.FullName -Raw | ConvertFrom-Json
|
||||||
|
|
||||||
if ((($vhdxCacheItem.WindowsSKU -ne $WindowsSKU) -or
|
if ((($vhdxCacheItem.WindowsSKU -ne $WindowsSKU) -or
|
||||||
([string]::IsNullOrEmpty($vhdxCacheItem.WindowsSKU) -xor [string]::IsNullOrEmpty($WindowsSKU)))) {
|
([string]::IsNullOrEmpty($vhdxCacheItem.WindowsSKU) -xor [string]::IsNullOrEmpty($WindowsSKU)))) {
|
||||||
WriteLog "WindowsSKU not equal"
|
WriteLog 'WindowsSKU mismatch, continuing'
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((($vhdxCacheItem.WindowsRelease -ne $WindowsRelease) -or
|
if ((($vhdxCacheItem.WindowsRelease -ne $WindowsRelease) -or
|
||||||
([string]::IsNullOrEmpty($vhdxCacheItem.WindowsRelease) -xor [string]::IsNullOrEmpty($WindowsRelease)))) {
|
([string]::IsNullOrEmpty($vhdxCacheItem.WindowsRelease) -xor [string]::IsNullOrEmpty($WindowsRelease)))) {
|
||||||
WriteLog "WindowsRelease not equal"
|
WriteLog 'WindowsRelease mismatch, continuing'
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((($vhdxCacheItem.WindowsVersion -ne $WindowsVersion) -or
|
if ((($vhdxCacheItem.WindowsVersion -ne $WindowsVersion) -or
|
||||||
([string]::IsNullOrEmpty($vhdxCacheItem.WindowsVersion) -xor [string]::IsNullOrEmpty($WindowsVersion)))) {
|
([string]::IsNullOrEmpty($vhdxCacheItem.WindowsVersion) -xor [string]::IsNullOrEmpty($WindowsVersion)))) {
|
||||||
WriteLog "WindowsVersion not equal"
|
Writelog 'WindowsVersion mismatch, continuing'
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((($vhdxCacheItem.OptionalFeatures -ne $OptionalFeatures) -or
|
if ((($vhdxCacheItem.OptionalFeatures -ne $OptionalFeatures) -or
|
||||||
([string]::IsNullOrEmpty($vhdxCacheItem.OptionalFeatures) -xor [string]::IsNullOrEmpty($OptionalFeatures)))) {
|
([string]::IsNullOrEmpty($vhdxCacheItem.OptionalFeatures) -xor [string]::IsNullOrEmpty($OptionalFeatures)))) {
|
||||||
WriteLog "OptionalFeatures not equal"
|
WriteLog 'OptionalFeatures mismatch, continuing'
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4300,11 +4315,11 @@ try {
|
|||||||
(Compare-Object -ReferenceObject $downloadedKBs -DifferenceObject $vhdxCacheItem.IncludedUpdates -Property Name)
|
(Compare-Object -ReferenceObject $downloadedKBs -DifferenceObject $vhdxCacheItem.IncludedUpdates -Property Name)
|
||||||
$downloadedKBs.Name
|
$downloadedKBs.Name
|
||||||
$vhdxCacheItem.IncludedUpdates.Name
|
$vhdxCacheItem.IncludedUpdates.Name
|
||||||
WriteLog "Updates not equal"
|
WriteLog 'IncludedUpdates mismatch, continuing'
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteLog "Found cached VHDX file with same parameters and patches"
|
WriteLog "Found cached VHDX file $vhdxCacheFolder\$($vhdxCacheItem.VhdxFileName) with matching parameters and included updates"
|
||||||
$cachedVHDXFileFound = $true
|
$cachedVHDXFileFound = $true
|
||||||
$cachedVHDXInfo = $vhdxCacheItem
|
$cachedVHDXInfo = $vhdxCacheItem
|
||||||
break
|
break
|
||||||
@@ -4318,8 +4333,7 @@ try {
|
|||||||
if (-Not $cachedVHDXFileFound) {
|
if (-Not $cachedVHDXFileFound) {
|
||||||
if ($ISOPath) {
|
if ($ISOPath) {
|
||||||
$wimPath = Get-WimFromISO
|
$wimPath = Get-WimFromISO
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
$wimPath = Get-WindowsESD -WindowsRelease $WindowsRelease -WindowsArch $WindowsArch -WindowsLang $WindowsLang -MediaType $mediaType
|
$wimPath = Get-WindowsESD -WindowsRelease $WindowsRelease -WindowsArch $WindowsArch -WindowsLang $WindowsLang -MediaType $mediaType
|
||||||
}
|
}
|
||||||
#If index not specified by user, try and find based on WindowsSKU
|
#If index not specified by user, try and find based on WindowsSKU
|
||||||
@@ -4335,27 +4349,15 @@ try {
|
|||||||
|
|
||||||
$osPartition = New-OSPartition -VhdxDisk $vhdxDisk -OSPartitionSize $OSPartitionSize -WimPath $WimPath -WimIndex $index
|
$osPartition = New-OSPartition -VhdxDisk $vhdxDisk -OSPartitionSize $OSPartitionSize -WimPath $WimPath -WimIndex $index
|
||||||
$osPartitionDriveLetter = $osPartition[1].DriveLetter
|
$osPartitionDriveLetter = $osPartition[1].DriveLetter
|
||||||
$WindowsPartition = $osPartitionDriveLetter + ":\"
|
$WindowsPartition = $osPartitionDriveLetter + ':\'
|
||||||
|
|
||||||
#$recoveryPartition = New-RecoveryPartition -VhdxDisk $vhdxDisk -OsPartition $osPartition[1] -RecoveryPartitionSize $RecoveryPartitionSize -DataPartition $dataPartition
|
#$recoveryPartition = New-RecoveryPartition -VhdxDisk $vhdxDisk -OsPartition $osPartition[1] -RecoveryPartitionSize $RecoveryPartitionSize -DataPartition $dataPartition
|
||||||
$recoveryPartition = New-RecoveryPartition -VhdxDisk $vhdxDisk -OsPartition $osPartition[1] -RecoveryPartitionSize $RecoveryPartitionSize -DataPartition $dataPartition
|
$recoveryPartition = New-RecoveryPartition -VhdxDisk $vhdxDisk -OsPartition $osPartition[1] -RecoveryPartitionSize $RecoveryPartitionSize -DataPartition $dataPartition
|
||||||
|
|
||||||
WriteLog "All necessary partitions created."
|
WriteLog 'All necessary partitions created.'
|
||||||
|
|
||||||
Add-BootFiles -OsPartitionDriveLetter $osPartitionDriveLetter -SystemPartitionDriveLetter $systemPartitionDriveLetter[1]
|
Add-BootFiles -OsPartitionDriveLetter $osPartitionDriveLetter -SystemPartitionDriveLetter $systemPartitionDriveLetter[1]
|
||||||
|
|
||||||
if ($UpdateLatestCU -or $UpdateLatestNet -or $UpdatePreviewCU ) {
|
|
||||||
#Check if $KBCachePath exists, if not, create it
|
|
||||||
if ($AllowUpdateCaching) {
|
|
||||||
if (-not (Test-Path -Path $KBCachePath)) {
|
|
||||||
WriteLog "Creating $KBCachePath"
|
|
||||||
New-Item -Path $KBCachePath -ItemType Directory -Force | Out-Null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#Add Windows packages
|
#Add Windows packages
|
||||||
if ($UpdateLatestCU -or $UpdateLatestNet -or $UpdatePreviewCU ) {
|
if ($UpdateLatestCU -or $UpdateLatestNet -or $UpdatePreviewCU ) {
|
||||||
try {
|
try {
|
||||||
@@ -4363,7 +4365,7 @@ try {
|
|||||||
WriteLog 'This can take 10+ minutes depending on how old the media is and the size of the KB. Please be patient'
|
WriteLog 'This can take 10+ minutes depending on how old the media is and the size of the KB. Please be patient'
|
||||||
# If WindowsRelease is 2016, we need to add the SSU first
|
# If WindowsRelease is 2016, we need to add the SSU first
|
||||||
if ($WindowsRelease -eq 2016) {
|
if ($WindowsRelease -eq 2016) {
|
||||||
WriteLog "WindowsRelease is 2016, adding SSU first"
|
WriteLog 'WindowsRelease is 2016, adding SSU first'
|
||||||
WriteLog "Adding SSU to $WindowsPartition"
|
WriteLog "Adding SSU to $WindowsPartition"
|
||||||
# Add-WindowsPackage -Path $WindowsPartition -PackagePath $SSUFilePath -PreventPending | Out-Null
|
# Add-WindowsPackage -Path $WindowsPartition -PackagePath $SSUFilePath -PreventPending | Out-Null
|
||||||
# Commenting out -preventpending as it causes an issue with the SSU being applied
|
# Commenting out -preventpending as it causes an issue with the SSU being applied
|
||||||
@@ -4388,12 +4390,11 @@ try {
|
|||||||
}
|
}
|
||||||
WriteLog "Removing $KBPath"
|
WriteLog "Removing $KBPath"
|
||||||
Remove-Item -Path $KBPath -Recurse -Force | Out-Null
|
Remove-Item -Path $KBPath -Recurse -Force | Out-Null
|
||||||
WriteLog "Clean Up the WinSxS Folder"
|
WriteLog 'Clean Up the WinSxS Folder'
|
||||||
WriteLog 'This can take 10+ minutes depending on how old the media is and the size of the KB. Please be patient'
|
WriteLog 'This can take 10+ minutes depending on how old the media is and the size of the KB. Please be patient'
|
||||||
Dism /Image:$WindowsPartition /Cleanup-Image /StartComponentCleanup /ResetBase | Out-Null
|
Dism /Image:$WindowsPartition /Cleanup-Image /StartComponentCleanup /ResetBase | Out-Null
|
||||||
WriteLog "Clean Up the WinSxS Folder completed"
|
WriteLog 'Clean Up the WinSxS Folder completed'
|
||||||
}
|
} catch {
|
||||||
catch {
|
|
||||||
Write-Host "Adding KB to VHDX failed with error $_"
|
Write-Host "Adding KB to VHDX failed with error $_"
|
||||||
WriteLog "Adding KB to VHDX failed with error $_"
|
WriteLog "Adding KB to VHDX failed with error $_"
|
||||||
if ($_.Exception.HResult -eq -2146498525) {
|
if ($_.Exception.HResult -eq -2146498525) {
|
||||||
@@ -4410,22 +4411,22 @@ try {
|
|||||||
|
|
||||||
#Enable Windows Optional Features (e.g. .Net3, etc)
|
#Enable Windows Optional Features (e.g. .Net3, etc)
|
||||||
If ($OptionalFeatures) {
|
If ($OptionalFeatures) {
|
||||||
$Source = Join-Path (Split-Path $wimpath) "sxs"
|
$Source = Join-Path (Split-Path $wimpath) 'sxs'
|
||||||
Enable-WindowsFeaturesByName -FeatureNames $OptionalFeatures -Source $Source
|
Enable-WindowsFeaturesByName -FeatureNames $OptionalFeatures -Source $Source
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
#Use cached vhdx file
|
#Use cached vhdx file
|
||||||
WriteLog "Using cached VHDX file to speed up build proces"
|
WriteLog 'Using cached VHDX file to speed up build proces'
|
||||||
WriteLog "VHDX file is: $($cachedVHDXInfo.VhdxFileName)"
|
WriteLog "VHDX file is: $($cachedVHDXInfo.VhdxFileName)"
|
||||||
|
|
||||||
Robocopy.exe $($VHDXCacheFolder) $($VMPath) $($cachedVHDXInfo.VhdxFileName) /E /COPY:DAT /R:5 /W:5 /J
|
Robocopy.exe $($VHDXCacheFolder) $($VMPath) $($cachedVHDXInfo.VhdxFileName) /E /COPY:DAT /R:5 /W:5 /J
|
||||||
$VHDXPath = Join-Path $($VMPath) $($cachedVHDXInfo.VhdxFileName)
|
$VHDXPath = Join-Path $($VMPath) $($cachedVHDXInfo.VhdxFileName)
|
||||||
|
|
||||||
$vhdxDisk = Get-VHD -Path $VHDXPath | Mount-VHD -Passthru | Get-Disk
|
$vhdxDisk = Get-VHD -Path $VHDXPath | Mount-VHD -Passthru | Get-Disk
|
||||||
$osPartition = $vhdxDisk | Get-Partition | Where-Object { $_.GptType -eq "{ebd0a0a2-b9e5-4433-87c0-68b6b72699c7}" }
|
$osPartition = $vhdxDisk | Get-Partition | Where-Object { $_.GptType -eq '{ebd0a0a2-b9e5-4433-87c0-68b6b72699c7}' }
|
||||||
$osPartitionDriveLetter = $osPartition.DriveLetter
|
$osPartitionDriveLetter = $osPartition.DriveLetter
|
||||||
$WindowsPartition = $osPartitionDriveLetter + ":\"
|
$WindowsPartition = $osPartitionDriveLetter + ':\'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4439,9 +4440,11 @@ try {
|
|||||||
Dismount-DiskImage -ImagePath $ISOPath | Out-null
|
Dismount-DiskImage -ImagePath $ISOPath | Out-null
|
||||||
WriteLog 'Done'
|
WriteLog 'Done'
|
||||||
}
|
}
|
||||||
else {
|
#If $wimPath is an esd file, remove it
|
||||||
#Remove ESD file
|
If ($wimPath -match '.esd') {
|
||||||
|
WriteLog "Deleting $wimPath file"
|
||||||
Remove-Item -Path $wimPath -Force
|
Remove-Item -Path $wimPath -Force
|
||||||
|
WriteLog "$wimPath deleted"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4459,12 +4462,12 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($AllowVHDXCaching -and !$cachedVHDXFileFound) {
|
if ($AllowVHDXCaching -and !$cachedVHDXFileFound) {
|
||||||
WriteLog 'New cachabe VHDX created'
|
WriteLog 'New cached VHDX created'
|
||||||
|
|
||||||
WriteLog 'Defragmenting Windows partition...'
|
WriteLog 'Defragmenting Windows partition...'
|
||||||
Optimize-Volume -DriveLetter $osPartition.DriveLetter -Defrag -NormalPriority -Verbose
|
Optimize-Volume -DriveLetter $osPartition.DriveLetter -Defrag -NormalPriority
|
||||||
WriteLog 'Performing slab consolidation on Windows partition...'
|
WriteLog 'Performing slab consolidation on Windows partition...'
|
||||||
Optimize-Volume -DriveLetter $osPartition.DriveLetter -SlabConsolidate -NormalPriority -Verbose
|
Optimize-Volume -DriveLetter $osPartition.DriveLetter -SlabConsolidate -NormalPriority
|
||||||
WriteLog 'Dismounting VHDX'
|
WriteLog 'Dismounting VHDX'
|
||||||
Dismount-ScratchVhdx -VhdxPath $VHDXPath
|
Dismount-ScratchVhdx -VhdxPath $VHDXPath
|
||||||
|
|
||||||
@@ -4737,19 +4740,29 @@ If ($CleanupAppsISO) {
|
|||||||
Writelog "Removing $AppsISO failed with error $_"
|
Writelog "Removing $AppsISO failed with error $_"
|
||||||
throw $_
|
throw $_
|
||||||
}
|
}
|
||||||
|
}
|
||||||
If ($CleanupDrivers) {
|
If ($CleanupDrivers) {
|
||||||
try {
|
try {
|
||||||
If (Test-Path -Path $Driversfolder\$Make) {
|
If (Test-Path -Path $Driversfolder\$Make) {
|
||||||
WriteLog "Removing $Driversfolder\$Make"
|
WriteLog "Removing $Driversfolder\$Make"
|
||||||
Remove-Item -Path $Driversfolder\$Make -Force -Recurse
|
Remove-Item -Path $Driversfolder\$Make -Force -Recurse
|
||||||
WriteLog "Removal complete"
|
WriteLog 'Removal complete'
|
||||||
}
|
}
|
||||||
}
|
} catch {
|
||||||
catch {
|
|
||||||
Writelog "Removing $Driversfolder\$Make failed with error $_"
|
Writelog "Removing $Driversfolder\$Make failed with error $_"
|
||||||
throw $_
|
throw $_
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if ($AllowVHDXCaching) {
|
||||||
|
try {
|
||||||
|
If (Test-Path -Path $KBPath) {
|
||||||
|
WriteLog "Removing $KBPath"
|
||||||
|
Remove-Item -Path $KBPath -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
WriteLog 'Removal complete'
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Writelog "Removing $KBPath failed with error $_"
|
||||||
|
throw $_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#Clean up dirty.txt file
|
#Clean up dirty.txt file
|
||||||
|
|||||||
Reference in New Issue
Block a user