From b7b4a53b0692d5132de8f0a584f313b02e53bfe8 Mon Sep 17 00:00:00 2001 From: rbalsleyMSFT Date: Fri, 2 Jun 2023 13:55:49 -0700 Subject: [PATCH] 2306.1.1 Included some better error handling if defining optionalfeatures that require source folders (netfx3). ESD files don't have source folders like ISO media, which means installing .net 3.5 as an optional feature would fail. Also cleaned up some formatting. --- FFUDevelopment/BuildFFUVM.ps1 | 142 ++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 65 deletions(-) diff --git a/FFUDevelopment/BuildFFUVM.ps1 b/FFUDevelopment/BuildFFUVM.ps1 index 3ebe9ed..ed6d1ec 100644 --- a/FFUDevelopment/BuildFFUVM.ps1 +++ b/FFUDevelopment/BuildFFUVM.ps1 @@ -121,6 +121,7 @@ param( [ValidateScript({ $allowedSKUs = @('Home', 'Home N', 'Home Single Language', 'Education', 'Education N', 'Pro', 'Pro N', 'Pro Education', 'Pro Education N', 'Pro for Workstations', 'Pro N for Workstations', 'Enterprise', 'Enterprise N') if ($allowedSKUs -contains $_) { $true } else { throw "Invalid WindowsSKU value. Allowed values: $($allowedSKUs -join ', ')" } + return $true })] [string]$WindowsSKU = 'Pro', [ValidateScript({ Test-Path $_ })] @@ -145,44 +146,38 @@ param( [String]$ShareName = "FFUCaptureShare", [string]$Username = "ffu_user", [Parameter(Mandatory = $false)] - [ValidateScript({ - if (($InstallApps -and ($_ -eq $null)) -or (-not ($ISOPath) -and ($_ -eq $null))) { - throw "If variable InstallApps is set to `$true, VMHostIPAddress must also be set to capture the FFU" - } - return $true - })] [string]$VMHostIPAddress, [bool]$CreateCaptureMedia = $true, [bool]$CreateDeploymentMedia, [ValidateScript({ - $allowedFeatures = @("Windows-Defender-Default-Definitions","Printing-PrintToPDFServices-Features","Printing-XPSServices-Features","TelnetClient","TFTP", - "TIFFIFilter","LegacyComponents","DirectPlay","MSRDC-Infrastructure","Windows-Identity-Foundation","MicrosoftWindowsPowerShellV2Root","MicrosoftWindowsPowerShellV2", - "SimpleTCP","NetFx4-AdvSrvs","NetFx4Extended-ASPNET45","WCF-Services45","WCF-HTTP-Activation45","WCF-TCP-Activation45","WCF-Pipe-Activation45","WCF-MSMQ-Activation45", - "WCF-TCP-PortSharing45","IIS-WebServerRole","IIS-WebServer","IIS-CommonHttpFeatures","IIS-HttpErrors","IIS-HttpRedirect","IIS-ApplicationDevelopment","IIS-Security", - "IIS-RequestFiltering","IIS-NetFxExtensibility","IIS-NetFxExtensibility45","IIS-HealthAndDiagnostics","IIS-HttpLogging","IIS-LoggingLibraries","IIS-RequestMonitor", - "IIS-HttpTracing","IIS-URLAuthorization","IIS-IPSecurity","IIS-Performance","IIS-HttpCompressionDynamic","IIS-WebServerManagementTools","IIS-ManagementScriptingTools", - "IIS-IIS6ManagementCompatibility","IIS-Metabase","WAS-WindowsActivationService","WAS-ProcessModel","WAS-NetFxEnvironment","WAS-ConfigurationAPI","IIS-HostableWebCore", - "WCF-HTTP-Activation","WCF-NonHTTP-Activation","IIS-StaticContent","IIS-DefaultDocument","IIS-DirectoryBrowsing","IIS-WebDAV","IIS-WebSockets","IIS-ApplicationInit", - "IIS-ISAPIFilter","IIS-ISAPIExtensions","IIS-ASPNET","IIS-ASPNET45","IIS-ASP","IIS-CGI","IIS-ServerSideIncludes","IIS-CustomLogging","IIS-BasicAuthentication", - "IIS-HttpCompressionStatic","IIS-ManagementConsole","IIS-ManagementService","IIS-WMICompatibility","IIS-LegacyScripts","IIS-LegacySnapIn","IIS-FTPServer","IIS-FTPSvc", - "IIS-FTPExtensibility","MSMQ-Container","MSMQ-DCOMProxy","MSMQ-Server","MSMQ-ADIntegration","MSMQ-HTTP","MSMQ-Multicast","MSMQ-Triggers","IIS-CertProvider", - "IIS-WindowsAuthentication","IIS-DigestAuthentication","IIS-ClientCertificateMappingAuthentication","IIS-IISCertificateMappingAuthentication","IIS-ODBCLogging", - "NetFx3","SMB1Protocol-Deprecation","MediaPlayback","WindowsMediaPlayer","Client-DeviceLockdown","Client-EmbeddedShellLauncher","Client-EmbeddedBootExp", - "Client-EmbeddedLogon","Client-KeyboardFilter","Client-UnifiedWriteFilter","HostGuardian","MultiPoint-Connector","MultiPoint-Connector-Services","MultiPoint-Tools" - ,"AppServerClient","SearchEngine-Client-Package","WorkFolders-Client","Printing-Foundation-Features","Printing-Foundation-InternetPrinting-Client", - "Printing-Foundation-LPDPrintService","Printing-Foundation-LPRPortMonitor","HypervisorPlatform","VirtualMachinePlatform","Microsoft-Windows-Subsystem-Linux", - "Client-ProjFS","Containers-DisposableClientVM",'Containers-DisposableClientVM','Microsoft-Hyper-V-All','Microsoft-Hyper-V','Microsoft-Hyper-V-Tools-All', - 'Microsoft-Hyper-V-Management-PowerShell','Microsoft-Hyper-V-Hypervisor','Microsoft-Hyper-V-Services','Microsoft-Hyper-V-Management-Clients','DataCenterBridging', - 'DirectoryServices-ADAM-Client','Windows-Defender-ApplicationGuard','ServicesForNFS-ClientOnly','ClientForNFS-Infrastructure','NFS-Administration','Containers','Containers-HNS', - 'Containers-SDN','SMB1Protocol','SMB1Protocol-Client','SMB1Protocol-Server','SmbDirect') - $inputFeatures = $_ -split ';' - foreach ($feature in $inputFeatures) { - if (-not ($allowedFeatures -contains $feature)) { - throw "Invalid optional feature '$feature'. Allowed values: $($allowedFeatures -join ', ')" + $allowedFeatures = @("Windows-Defender-Default-Definitions", "Printing-PrintToPDFServices-Features", "Printing-XPSServices-Features", "TelnetClient", "TFTP", + "TIFFIFilter", "LegacyComponents", "DirectPlay", "MSRDC-Infrastructure", "Windows-Identity-Foundation", "MicrosoftWindowsPowerShellV2Root", "MicrosoftWindowsPowerShellV2", + "SimpleTCP", "NetFx4-AdvSrvs", "NetFx4Extended-ASPNET45", "WCF-Services45", "WCF-HTTP-Activation45", "WCF-TCP-Activation45", "WCF-Pipe-Activation45", "WCF-MSMQ-Activation45", + "WCF-TCP-PortSharing45", "IIS-WebServerRole", "IIS-WebServer", "IIS-CommonHttpFeatures", "IIS-HttpErrors", "IIS-HttpRedirect", "IIS-ApplicationDevelopment", "IIS-Security", + "IIS-RequestFiltering", "IIS-NetFxExtensibility", "IIS-NetFxExtensibility45", "IIS-HealthAndDiagnostics", "IIS-HttpLogging", "IIS-LoggingLibraries", "IIS-RequestMonitor", + "IIS-HttpTracing", "IIS-URLAuthorization", "IIS-IPSecurity", "IIS-Performance", "IIS-HttpCompressionDynamic", "IIS-WebServerManagementTools", "IIS-ManagementScriptingTools", + "IIS-IIS6ManagementCompatibility", "IIS-Metabase", "WAS-WindowsActivationService", "WAS-ProcessModel", "WAS-NetFxEnvironment", "WAS-ConfigurationAPI", "IIS-HostableWebCore", + "WCF-HTTP-Activation", "WCF-NonHTTP-Activation", "IIS-StaticContent", "IIS-DefaultDocument", "IIS-DirectoryBrowsing", "IIS-WebDAV", "IIS-WebSockets", "IIS-ApplicationInit", + "IIS-ISAPIFilter", "IIS-ISAPIExtensions", "IIS-ASPNET", "IIS-ASPNET45", "IIS-ASP", "IIS-CGI", "IIS-ServerSideIncludes", "IIS-CustomLogging", "IIS-BasicAuthentication", + "IIS-HttpCompressionStatic", "IIS-ManagementConsole", "IIS-ManagementService", "IIS-WMICompatibility", "IIS-LegacyScripts", "IIS-LegacySnapIn", "IIS-FTPServer", "IIS-FTPSvc", + "IIS-FTPExtensibility", "MSMQ-Container", "MSMQ-DCOMProxy", "MSMQ-Server", "MSMQ-ADIntegration", "MSMQ-HTTP", "MSMQ-Multicast", "MSMQ-Triggers", "IIS-CertProvider", + "IIS-WindowsAuthentication", "IIS-DigestAuthentication", "IIS-ClientCertificateMappingAuthentication", "IIS-IISCertificateMappingAuthentication", "IIS-ODBCLogging", + "NetFx3", "SMB1Protocol-Deprecation", "MediaPlayback", "WindowsMediaPlayer", "Client-DeviceLockdown", "Client-EmbeddedShellLauncher", "Client-EmbeddedBootExp", + "Client-EmbeddedLogon", "Client-KeyboardFilter", "Client-UnifiedWriteFilter", "HostGuardian", "MultiPoint-Connector", "MultiPoint-Connector-Services", "MultiPoint-Tools" + , "AppServerClient", "SearchEngine-Client-Package", "WorkFolders-Client", "Printing-Foundation-Features", "Printing-Foundation-InternetPrinting-Client", + "Printing-Foundation-LPDPrintService", "Printing-Foundation-LPRPortMonitor", "HypervisorPlatform", "VirtualMachinePlatform", "Microsoft-Windows-Subsystem-Linux", + "Client-ProjFS", "Containers-DisposableClientVM", 'Containers-DisposableClientVM', 'Microsoft-Hyper-V-All', 'Microsoft-Hyper-V', 'Microsoft-Hyper-V-Tools-All', + 'Microsoft-Hyper-V-Management-PowerShell', 'Microsoft-Hyper-V-Hypervisor', 'Microsoft-Hyper-V-Services', 'Microsoft-Hyper-V-Management-Clients', 'DataCenterBridging', + 'DirectoryServices-ADAM-Client', 'Windows-Defender-ApplicationGuard', 'ServicesForNFS-ClientOnly', 'ClientForNFS-Infrastructure', 'NFS-Administration', 'Containers', 'Containers-HNS', + 'Containers-SDN', 'SMB1Protocol', 'SMB1Protocol-Client', 'SMB1Protocol-Server', 'SmbDirect') + $inputFeatures = $_ -split ';' + foreach ($feature in $inputFeatures) { + if (-not ($allowedFeatures -contains $feature)) { + throw "Invalid optional feature '$feature'. Allowed values: $($allowedFeatures -join ', ')" + } } - } - $true - })] + return $true + })] [string]$OptionalFeatures, [string]$ProductKey, [bool]$BuildUSBDrive, @@ -193,11 +188,12 @@ param( [ValidateSet('x86', 'x64')] [string]$WindowsArch = 'x64', [ValidateScript({ - $allowedLang = @('ar-sa','bg-bg','cs-cz','da-dk','de-de','el-gr','en-gb','en-us','es-es','es-mx','et-ee','fi-fi','fr-ca','fr-fr','he-il','hr-hr','hu-hu', - 'it-it','ja-jp','ko-kr','lt-lt','lv-lv','nb-no','nl-nl','pl-pl','pt-br','pt-pt','ro-ro','ru-ru','sk-sk','sl-si','sr-latn-rs','sv-se','th-th','tr-tr','uk-ua', - 'zh-cn','zh-tw') - if ($allowedLang -contains $_) { $true } else { throw "Invalid WindowsLang value. Allowed values: $($allowedLang -join ', ')" } - })] + $allowedLang = @('ar-sa', 'bg-bg', 'cs-cz', 'da-dk', 'de-de', 'el-gr', 'en-gb', 'en-us', 'es-es', 'es-mx', 'et-ee', 'fi-fi', 'fr-ca', 'fr-fr', 'he-il', 'hr-hr', 'hu-hu', + 'it-it', 'ja-jp', 'ko-kr', 'lt-lt', 'lv-lv', 'nb-no', 'nl-nl', 'pl-pl', 'pt-br', 'pt-pt', 'ro-ro', 'ru-ru', 'sk-sk', 'sl-si', 'sr-latn-rs', 'sv-se', 'th-th', 'tr-tr', 'uk-ua', + 'zh-cn', 'zh-tw') + if ($allowedLang -contains $_) { $true } else { throw "Invalid WindowsLang value. Allowed values: $($allowedLang -join ', ')" } + return $true + })] [Parameter(Mandatory = $false)] [string]$WindowsLang = 'en-us', [Parameter(Mandatory = $false)] @@ -206,11 +202,7 @@ param( [ValidateSet(512, 4096)] [uint32]$LogicalSectorSizeBytes = 512 ) -$version = '2306.1' - -if (($InstallOffice -eq $true) -and ($InstallApps -eq $false)) { - throw "If variable InstallOffice is set to `$true, InstallApps must also be set to `$true." -} +$version = '2306.1.1' #Check if Hyper-V feature is installed (requires only checks the module) $osInfo = Get-WmiObject -Class Win32_OperatingSystem @@ -376,18 +368,18 @@ Function Get-ADK { } function Get-WindowsESD { param( - [Parameter(Mandatory=$false)] + [Parameter(Mandatory = $false)] [ValidateSet(10, 11)] [int]$WindowsRelease, - [Parameter(Mandatory=$false)] + [Parameter(Mandatory = $false)] [ValidateSet('x86', 'x64')] [string]$WindowsArch, - [Parameter(Mandatory=$false)] + [Parameter(Mandatory = $false)] [string]$WindowsLang, - [Parameter(Mandatory=$false)] + [Parameter(Mandatory = $false)] [ValidateSet('consumer', 'business')] [string]$MediaType ) @@ -399,7 +391,8 @@ function Get-WindowsESD { # Select cab file URL based on Windows Release $cabFileUrl = if ($WindowsRelease -eq 10) { 'https://go.microsoft.com/fwlink/?LinkId=841361' - } else { + } + else { 'https://go.microsoft.com/fwlink/?LinkId=2156292' } @@ -519,7 +512,7 @@ function Get-WimFromISO { # Check for install.wim or install.esd $wimPath = (Get-ChildItem $sourcesFolder\install.* | Where-Object { $_.Name -match "install\.(wim|esd)" }).FullName - if($wimPath) { + if ($wimPath) { WriteLog "The path to the install file is: $wimPath" } else { @@ -537,7 +530,7 @@ function Get-WimIndex { ) WriteLog "Getting WIM Index for Windows SKU: $WindowsSKU" - If($ISOPath){ + If ($ISOPath) { $wimindex = switch ($WindowsSKU) { 'Home' { 1 } 'Home_N' { 2 } @@ -1267,15 +1260,32 @@ Write-Host "FFU build process has begun. This process can take 20 minutes or mor Write-Host "To track progress, please open the log file $Logfile or use the -Verbose parameter next time" WriteLog 'Begin Logging' -#Get script variable values -LogVariableValues #Override $InstallApps value if using ESD to build FFU. This is due to a strange issue where building the FFU #from vhdx doesn't work (you get an older style OOBE screen and get stuck in an OOBE reboot loop when hitting next). #This behavior doesn't happen with WIM files. -If(-not ($ISOPath)){ +If (-not ($ISOPath) -and (-not ($InstallApps))) { $InstallApps = $true -} + WriteLog "Script will download Windows media. Setting `$InstallApps to `$true to build VM to capture FFU. Must do this when using MCT ESD." +} + +if (($InstallOffice -eq $true) -and ($InstallApps -eq $false)) { + throw "If variable InstallOffice is set to `$true, InstallApps must also be set to `$true." +} +if (($InstallApps -and ($VMSwitchName -eq ''))) { + throw "If variable InstallApps is set to `$true, VMSwitchName must also be set to capture the FFU. Please set -VMSwitchName and try again." +} + +if (($InstallApps -and ($VMHostIPAddress -eq ''))) { + throw "If variable InstallApps is set to `$true, VMHostIPAddress must also be set to capture the FFU. Please set -VMHostIPAddress and try again." +} + +if (-not ($ISOPath) -and ($OptionalFeatures -like '*netfx3*')) { + throw "netfx3 specified as an optional feature, however Windows ISO isn't defined. Unable to get netfx3 source files from downloaded ESD media. Please specify a Windows ISO in the ISOPath parameter." +} + +#Get script variable values +LogVariableValues #Get Windows ADK try { @@ -1327,14 +1337,14 @@ if ($InstallApps) { #Create VHDX try { - if($ISOPath){ + if ($ISOPath) { $wimPath = Get-WimFromISO } - else{ + else { $wimPath = Get-WindowsESD -WindowsRelease $WindowsRelease -WindowsArch $WindowsArch -WindowsLang $WindowsLang -MediaType $mediaType } #If index not specified by user, try and find based on WindowsSKU - if (-not($index) -and ($WindowsSKU)){ + if (-not($index) -and ($WindowsSKU)) { $index = Get-Index -WindowsImagePath $wimPath -WindowsSKU $WindowsSKU } @@ -1370,7 +1380,7 @@ try { Dismount-DiskImage -ImagePath $ISOPath | Out-null WriteLog 'Done' } - else{ + else { #Remove ESD file Remove-Item -Path $wimPath -Force } @@ -1398,9 +1408,11 @@ catch { Dismount-DiskImage -ImagePath $ISOPath | Out-null WriteLog 'Done' } - else{ + else { #Remove ESD file - Remove-Item -Path $esdFilePath -Force + WriteLog "Deleting ESD file" + Remove-Item -Path $wimPath -Force + WriteLog "ESD File deleted" } throw $_ @@ -1517,17 +1529,17 @@ If ($CreateDeploymentMedia) { } } -If($BuildUSBDrive){ - try{ - If(Test-Path -Path "$FFUDevelopmentPath\WinPE_FFU_Deploy.iso"){ +If ($BuildUSBDrive) { + try { + If (Test-Path -Path "$FFUDevelopmentPath\WinPE_FFU_Deploy.iso") { New-DeploymentUSB -CopyFFU } - else{ + else { WriteLog "$BuildUSBDrive set to true, however unable to find WinPE_FFU_Deploy.iso. USB drive not built." } } - catch{ + catch { Write-Host 'Building USB deployment drive failed' Writelog "Building USB deployment drive failed with error $_" throw $_