Public/New-OSBuildMultiLang.ps1
<#
.SYNOPSIS Separates an OSBuild with Language Packs into separate Image Indexes .DESCRIPTION Separates an OSBuild with Language Packs into separate Image Indexes. This will create a new OSBuild .LINK https://osdbuilder.osdeploy.com/module/functions/new-osbuildmultilang #> function New-OSBuildMultiLang { [CmdletBinding()] param ( #Name of the new OSBuild MultiLang to create. MultiLang will be appended to the end of CustomName [Parameter(Position = 0, Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$CustomName ) Begin { #================================================= # Header #================================================= # Write-Host '========================================================================================' -ForegroundColor DarkGray # Write-Host -ForegroundColor Green "$($MyInvocation.MyCommand.Name) BEGIN" #================================================= # Get-OSDBuilder #================================================= Get-OSDBuilder -CreatePaths -HideDetails #================================================= # Get-OSDUpdates #================================================= $AllOSDUpdates = @() $AllOSDUpdates = Get-OSDUpdates #================================================= # Block #================================================= Block-StandardUser #================================================= } Process { Write-Host '========================================================================================' -ForegroundColor DarkGray Write-Host -ForegroundColor Green "$($MyInvocation.MyCommand.Name) PROCESS" Write-Warning "OSBuild MultiLang will take an OSBuild with Language Packs" Write-Warning "and create a new OSBuild with multiple Indexes" Write-Warning "Each Index will have a Language set as the System UI" Write-Warning "This process will take some time as the LCU will be reapplied" #================================================= # Get OSBuilds with Multi Lang #================================================= $AllMyOSBuilds = @() $AllMyOSBuilds = Get-OSBuilds | Where-Object {($_.Languages).Count -gt 1} | Where-Object {$_.Name -notlike "*MultiLang"} #================================================= # Select Source OSBuild #================================================= $SelectedOSBuild = @() $SelectedOSBuild = $AllMyOSBuilds | Out-GridView -Title "OSDBuilder: Select one or more OSBuilds to split and press OK (Cancel to Exit)" -PassThru #================================================= # Build #================================================= foreach ($Media in $SelectedOSBuild) { $SourceFullName = "$($Media.FullName)" $BuildName = "$CustomName MultiLang" $DestinationFullName = "$SetOSDBuilderPathOSBuilds\$BuildName" $Info = "$DestinationFullName\info" #================================================= # Copy Media #================================================= Write-Host "Copying Media to $DestinationFullName" -ForegroundColor Cyan if (Test-Path $DestinationFullName) {Write-Warning "Existing contents will be replaced in $DestinationFullName"} robocopy "$SourceFullName" "$DestinationFullName" *.* /mir /ndl /nfl /b /np /ts /tee /r:0 /w:0 /xf install.wim *.iso *.vhd *.vhdx #================================================= # Process Languages #================================================= $LangMultiWindowsImage = Import-Clixml "$DestinationFullName\info\xml\Get-WindowsImage.xml" $LangMultiLanguages = $($LangMultiWindowsImage.Languages) [int]$LangMultiDefaultIndex = $($LangMultiWindowsImage.DefaultLanguageIndex) $LangMultiDefaultName = $LangMultiLanguages[$LangMultiDefaultIndex] #================================================= # #================================================= $RegValueCurrentBuild = $null if (Test-Path "$DestinationFullName\info\xml\CurrentVersion.xml") { $RegKeyCurrentVersion = Import-Clixml -Path "$DestinationFullName\info\xml\CurrentVersion.xml" [string]$RegValueCurrentBuild = ($RegKeyCurrentVersion).CurrentBuild [string]$RegValueDisplayVersion = ($RegKeyCurrentVersion).DisplayVersion [string]$ReleaseId = ($RegKeyCurrentVersion).ReleaseId if ($RegValueDisplayVersion) {$ReleaseId = $RegValueDisplayVersion} } #================================================= # Operating System #================================================= $OSArchitecture = $($LangMultiWindowsImage.Architecture) $OSBuild = $($LangMultiWindowsImage.Build) $OSInstallationType = $($LangMultiWindowsImage.InstallationType) $OSMajorVersion = $($LangMultiWindowsImage.MajorVersion) $WindowsImageMediaName = $($LangMultiWindowsImage.MediaName) $OSVersion = $($LangMultiWindowsImage.Version) if ($OSArchitecture -eq '0') {$OSArchitecture = 'x86'} if ($OSArchitecture -eq '6') {$OSArchitecture = 'ia64'} if ($OSArchitecture -eq '9') {$OSArchitecture = 'x64'} if ($OSArchitecture -eq '12') {$OSArchitecture = 'x64 ARM'} #================================================= # Operating System #================================================= $UpdateOS = '' if ($OSMajorVersion -eq 10) { if ($OSInstallationType -match 'Server') { $UpdateOS = 'Windows Server' } else { if ($WindowsImageMediaName -match ' 11 ') { $UpdateOS = 'Windows 11' } else { $UpdateOS = 'Windows 10' } } } #================================================= # OSDUpdateLCU #================================================= $OSDUpdateLCU = $AllOSDUpdates $OSDUpdateLCU = $OSDUpdateLCU | Where-Object {$_.UpdateArch -eq $OSArchitecture} $OSDUpdateLCU = $OSDUpdateLCU | Where-Object {$_.UpdateOS -eq $UpdateOS} $OSDUpdateLCU = $OSDUpdateLCU | Where-Object {($_.UpdateBuild -eq $ReleaseId) -or ($_.UpdateBuild -eq '')} $OSDUpdateLCU = $OSDUpdateLCU | Where-Object {$_.UpdateGroup -eq 'LCU'} #================================================= # Export Install.wim #================================================= if (Test-Path "$DestinationFullName\OS\Sources\install.wim") {Remove-Item -Path "$DestinationFullName\OS\Sources\install.wim" -Force | Out-Null} $TempInstallWim = Join-Path "$env:Temp" "install$((Get-Date).ToString('mmss')).wim" Write-Host "Exporting install.wim to $DestinationFullName\OS\Sources\install.wim" -ForegroundColor Cyan Export-WindowsImage -SourceImagePath "$SourceFullName\OS\Sources\install.wim" -SourceIndex 1 -DestinationImagePath "$DestinationFullName\OS\Sources\install.wim" -DestinationName "$($Media.ImageName) $LangMultiDefaultName" | Out-Null Write-Host "Exporting temporary install.wim to $TempInstallWim" -ForegroundColor Cyan Export-WindowsImage -SourceImagePath "$SourceFullName\OS\Sources\Install.wim" -SourceIndex 1 -DestinationImagePath "$TempInstallWim" -DestinationName "$($Media.ImageName)" | Out-Null $MountDirectory = Join-Path "$env:Temp" "mount$((Get-Date).ToString('mmss'))" New-Item "$MountDirectory" -ItemType Directory | Out-Null Mount-WindowsImage -Path "$MountDirectory" -ImagePath "$TempInstallWim" -Index 1 | Out-Null #================================================= # Process Indexes #================================================= foreach ($LangMultiLanguage in $LangMultiLanguages) { if ($LangMultiLanguage -eq $LangMultiDefaultName) { #================================================= # Header #================================================= Show-ActionTime Write-Host -ForegroundColor Green "$($Media.ImageName) $LangMultiDefaultName is already processed as Index 1" } else { Show-ActionTime Write-Host -ForegroundColor Green "Processing $($Media.ImageName) $LangMultiLanguage" Write-Host "Dism /Image:"$MountDirectory" /Set-AllIntl:$LangMultiLanguage" -ForegroundColor Cyan Dism /Image:"$MountDirectory" /Set-AllIntl:$LangMultiLanguage Write-Host "Dism /Image:"$MountDirectory" /Get-Intl" -ForegroundColor Cyan Dism /Image:"$MountDirectory" /Get-Intl Write-Warning "Waiting 10 seconds for processes to complete before applying LCU ..." Start-Sleep -Seconds 10 Update-CumulativeOS -Force Write-Warning "Waiting 10 seconds for processes to complete before Save-WindowsImage ..." Start-Sleep -Seconds 10 Save-WindowsImage -Path "$MountDirectory" | Out-Null Write-Warning "Waiting 10 seconds for processes to complete before Export-WindowsImage ..." Start-Sleep -Seconds 10 Export-WindowsImage -SourceImagePath "$TempInstallWim" -SourceIndex 1 -DestinationImagePath "$DestinationFullName\OS\Sources\install.wim" -DestinationName "$($Media.ImageName) $LangMultiLanguage" | Out-Null } } #================================================= # Cleanup #================================================= try { Write-Warning "Waiting 10 seconds for processes to complete before Dismount-WindowsImage ..." Start-Sleep -Seconds 10 Dismount-WindowsImage -Path "$MountDirectory" -Discard -ErrorAction SilentlyContinue | Out-Null } catch { Write-Warning "Could not dismount $MountDirectory ... Waiting 30 seconds ..." Start-Sleep -Seconds 30 Dismount-WindowsImage -Path "$MountDirectory" -Discard | Out-Null } Write-Warning "Waiting 10 seconds for processes to finish before removing Temporary Files ..." Start-Sleep -Seconds 10 Remove-Item -Path "$MountDirectory" -Force | Out-Null if (Test-Path "$TempInstallWim") {Remove-Item -Path "$TempInstallWim" -Force | Out-Null} } } End { #Write-Host '========================================================================================' -ForegroundColor DarkGray #Write-Host -ForegroundColor Green "$($MyInvocation.MyCommand.Name) END" } } |