Public/Update-OSMedia.ps1

<#
.SYNOPSIS
Applies Adobe, Component, Cumulative, Servicing Stack, and Setup Updates to Windows 10, Windows Server 2016, and Windows Server 2019 using Offline Servicing

.DESCRIPTION
Updates are gathered from the OSBuilder Update Catalogs

.PARAMETER ByName
Enter the name of the existing OSMedia to update

.EXAMPLE
Update-OSMedia -ByName 'Win10 Ent x64 1803 17134.345'

.PARAMETER DownloadUpdates
Automatically download the required updates if they are not present in the Content\Updates directory

.EXAMPLE
Update-OSMedia -ByName 'Win10 Ent x64 1803 17134.345' -DownloadUpdates

.PARAMETER Execute
Execute the Update

.EXAMPLE
Update-OSMedia -ByName 'Win10 Ent x64 1803 17134.345' -DownloadUpdates -Execute

.PARAMETER CreateISO
Creates an ISO of the Updated Media. Requires ADK oscdimg.exe

.EXAMPLE
Update-OSMedia -ByName 'Win10 Ent x64 1803 17134.345' -DownloadUpdates -Execute -CreateISO

.PARAMETER PromptBeforeDismount
Adds a 'Press Enter to Continue' prompt before the Install.wim is dismounted

.PARAMETER PromptBeforeDismountWinPE
Adds a 'Press Enter to Continue' prompt before WinPE is dismounted
#>

function Update-OSMedia {
    [CmdletBinding(DefaultParameterSetName='Basic')]
    Param (
        [switch]$CreateISO,
        [switch]$DownloadUpdates,
        [switch]$Execute,
        [Parameter(ParameterSetName='Advanced')]
        [string]$ByName,
        [Parameter(ParameterSetName='Advanced')]
        [switch]$PromptBeforeDismount,
        [Parameter(ParameterSetName='Advanced')]
        [switch]$PromptBeforeDismountWinPE
    )

#===================================================================================================
# 18.12.03 Start
#===================================================================================================
    Write-Host "===================================================================================================" -ForegroundColor Green
    Write-Host "Update-OSMedia" -ForegroundColor Green
    Write-Host "===================================================================================================" -ForegroundColor Green

#===================================================================================================
# 18.12.03 Validate Administrator Rights
#===================================================================================================
    if (!([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
        Write-Host ""
        Write-Host "OSBuilder: This function needs to be run as Administrator" -ForegroundColor Cyan
        Write-Host ""
        Return
    }

#===================================================================================================
# 18.12.03 Initialize OSBuilder
#===================================================================================================
    Get-OSBuilder -CreatePaths -HideDetails

#===================================================================================================
# 18.12.03 Validate OSMedia has Content
#===================================================================================================
    $AllOSMedia = @()
    $AllOSMedia = Get-ChildItem -Path "$OSBuilderOSMedia" -Directory | Where-Object {$_.Name -like "*.*"} | Select-Object -Property Name, FullName, CreationTime
    if ($null -eq $AllOSMedia) {
        Write-Warning "OSMedia content not found. Use Import-OSMedia to import an Operating System first . . . Exiting!"
        Break
    }

#===================================================================================================
# 18.12.03 Validate OSMedia has an install.wim
#===================================================================================================
    $AllOSMedia = $AllOSMedia | Where-Object {Test-Path $(Join-Path $_.FullName (Join-Path "OS" (Join-Path "sources" "install.wim")))}
    if ($null -eq $AllOSMedia) {
        Write-Warning "OSMedia Install.wim not found. Use Import-OSMedia to import an Operating System first . . . Exiting!"
        Break
    }

#===================================================================================================
# 18.12.03 Validate OSMedia was imported with Import-OSMedia
#===================================================================================================
    $AllOSMedia = $AllOSMedia | Where-Object {Test-Path $(Join-Path $_.FullName "WindowsImage.txt")}
    if ($null -eq $AllOSMedia) {
        Write-Warning "OSMedia content invalid (missing WindowsImage.txt). Use Import-OSMedia to import an Operating System first . . . Exiting!"
        Break
    }

#===================================================================================================
# 18.12.03 Select Source OSMedia
#===================================================================================================
    if ($ByName) {
        $AllOSMedia = $AllOSMedia | Where-Object {$_.Name -like "*$ByName*" -or $_.FullName -like "*$ByName*"}
        if ($null -eq $AllOSMedia) {
            Write-Warning "Could not find a matching OSMedia to update . . . Exiting!"
            Break
        }
    } else {
        $AllOSMedia = $AllOSMedia | Out-GridView -Title "Select one or more Source OSMedia to Update (Cancel to Exit)" -PassThru
        if($null -eq $AllOSMedia) {
            Write-Warning "Source OSMedia was not selected . . . Exiting!"
            Break
        }
    }
    if ($AllOSMedia.Count -gt 1) {
        Write-Warning "Updating Multiple Operating Systems. This may take some time ..."
    }

#===================================================================================================
# 18.12.03 Update OSMedia
#===================================================================================================
    foreach ($SelectedOSMedia in $AllOSMedia) {

#===================================================================================================
# 18.12.03 Get Windows Image Information
#===================================================================================================
        $OSSourcePath = "$($SelectedOSMedia.FullName)"
        $OSImagePath = "$OSSourcePath\OS\sources\install.wim"
        $OSImageIndex = 1
        $WindowsImage = Get-WindowsImage -ImagePath "$OSImagePath" -Index $OSImageIndex | Select-Object -Property *

        $OSImageName = $($WindowsImage.ImageName)
        $OSImageDescription = $($WindowsImage.ImageDescription)
        if ($($WindowsImage.Architecture) -eq 0) {$OSArchitecture = 'x86'}
        elseif ($($WindowsImage.Architecture) -eq 1) {$OSArchitecture = 'MIPS'}
        elseif ($($WindowsImage.Architecture) -eq 2) {$OSArchitecture = 'Alpha'}
        elseif ($($WindowsImage.Architecture) -eq 3) {$OSArchitecture = 'PowerPC'}
        elseif ($($WindowsImage.Architecture) -eq 6) {$OSArchitecture = 'ia64'}
        elseif ($($WindowsImage.Architecture) -eq 9) {$OSArchitecture = 'x64'}
        else {$OSArchitecture = $null}
        $OSEditionID = $($WindowsImage.EditionId)
        $OSInstallationType = $($WindowsImage.InstallationType)
        $OSLanguages = $($WindowsImage.Languages)
        $OSBuild = $($WindowsImage.Build)
        $OSVersion = $($WindowsImage.Version)
        $OSSPBuild = $($WindowsImage.SPBuild)
        $OSSPLevel = $($WindowsImage.SPLevel)
        $OSImageBootable = $($WindowsImage.ImageBootable)
        $OSWIMBoot = $($WindowsImage.WIMBoot)
        $OSCreatedTime = $($WindowsImage.CreatedTime)
        $OSModifiedTime = $($WindowsImage.ModifiedTime)
        #===================================================================================================
        Write-Host "OSMedia Information" -ForegroundColor Cyan
        Write-Host "-Source Path: $OSSourcePath" -ForegroundColor Cyan
        Write-Host "-Image File: $OSImagePath" -ForegroundColor Cyan
        Write-Host "-Image Index: $OSImageIndex" -ForegroundColor Cyan
        Write-Host "-Name: $OSImageName" -ForegroundColor Cyan
        Write-Host "-Description: $OSImageDescription" -ForegroundColor Cyan
        Write-Host "-Architecture: $OSArchitecture" -ForegroundColor Cyan
        Write-Host "-Edition: $OSEditionID" -ForegroundColor Cyan
        Write-Host "-Type: $OSInstallationType" -ForegroundColor Cyan
        Write-Host "-Languages: $OSLanguages" -ForegroundColor Cyan
        Write-Host "-Build: $OSBuild" -ForegroundColor Cyan
        Write-Host "-Version: $OSVersion" -ForegroundColor Cyan
        Write-Host "-SPBuild: $OSSPBuild" -ForegroundColor Cyan
        Write-Host "-SPLevel: $OSSPLevel" -ForegroundColor Cyan
        Write-Host "-Bootable: $OSImageBootable" -ForegroundColor Cyan
        Write-Host "-WimBoot: $OSWIMBoot" -ForegroundColor Cyan
        Write-Host "-Created Time: $OSCreatedTime" -ForegroundColor Cyan
        Write-Host "-Modified Time: $OSModifiedTime" -ForegroundColor Cyan
        #===================================================================================================
        if (Test-Path "$OSSourcePath\info\xml\CurrentVersion.xml") {
            $RegCurrentVersion = Import-Clixml -Path "$OSSourcePath\info\xml\CurrentVersion.xml"
            $OSVersionNumber = $($RegCurrentVersion.ReleaseId)            
            if ($OSVersionNumber -gt 1809) {
                Write-Warning "OSBuilder does not currently support this version of Windows ... Check for an updated version"
                #Write-Warning "OSBuilder cannot proceed . . . Exiting"
                #Return
            }
        } else {
            if ($OSBuild -eq 10240) {$OSVersionNumber = 1507}
            if ($OSBuild -eq 14393) {$OSVersionNumber = 1607}
            if ($OSBuild -eq 15063) {$OSVersionNumber = 1703}
            if ($OSBuild -eq 16299) {$OSVersionNumber = 1709}
            if ($OSBuild -eq 17134) {$OSVersionNumber = 1803}
            if ($OSBuild -eq 17763) {$OSVersionNumber = 1809}
        }

#===================================================================================================
# 18.12.03 Set Working Path
#===================================================================================================
        $BuildName = "build$((Get-Date).ToString('mmss'))"
        $WorkingPath = "$OSBuilderOSMedia\$BuildName"

#===================================================================================================
# 18.12.03 Validate Exiting WorkingPath
#===================================================================================================
        if (Test-Path $WorkingPath) {
            Write-Warning "$WorkingPath exists. Contents will be replaced"
            Remove-Item -Path "$WorkingPath" -Force -Recurse
            Write-Host ""
        }

#===================================================================================================
# 18.12.03 Update Catalogs
#===================================================================================================
        if ($DownloadUpdates.IsPresent) {Get-OSBuilderUpdates -UpdateCatalogs -HideDetails}
        if (!(Test-Path $CatalogLocal)) {Get-OSBuilderUpdates -UpdateCatalogs -HideDetails}

#===================================================================================================
# 18.12.03 Get Catalogs
#===================================================================================================
        $ImportCatalog = @()
        $CatalogDownloads = @()
        $CatalogsXmls = Get-ChildItem "$OSBuilderContent\Updates" *.xml -Recurse
        foreach ($CatalogsXml in $CatalogsXmls) {
            $ImportCatalog = Import-Clixml -Path "$($CatalogsXml.FullName)"
            $CatalogDownloads += $ImportCatalog
        }

#===================================================================================================
# 18.12.03 Adobe Updates
#===================================================================================================
        $UpdateCatAdobe = @()
        $UpdateCatAdobe = $CatalogDownloads | Where-Object {$_.Category -eq 'Adobe'}
        $UpdateCatAdobe = $UpdateCatAdobe | Where-Object {$_.KBTitle -like "*$OSVersionNumber*"}
        $UpdateCatAdobe = $UpdateCatAdobe | Where-Object {$_.KBTitle -like "*$OSArchitecture*"}
        if ($OSInstallationType -like "*Server*") {
            $UpdateCatAdobe = $UpdateCatAdobe | Where-Object {$_.KBTitle -like "*Server*"}
        } else {
            $UpdateCatAdobe = $UpdateCatAdobe | Where-Object {$_.KBTitle -notlike "*Server*"}
        }
        $UpdateCatAdobe = $UpdateCatAdobe | Sort-Object -Property DatePosted | Select-Object -Last 1

#===================================================================================================
# 18.12.03 Component Updates
#===================================================================================================
        $UpdateCatComponent = @()
        $UpdateCatComponent = $CatalogDownloads | Where-Object {$_.Category -eq 'Component'}
        $UpdateCatComponent = $UpdateCatComponent | Where-Object {$_.KBTitle -like "*$OSVersionNumber*"}
        $UpdateCatComponent = $UpdateCatComponent | Where-Object {$_.KBTitle -like "*$OSArchitecture*"}
        if ($OSInstallationType -like "*Server*") {
            $UpdateCatComponent = $UpdateCatComponent | Where-Object {$_.KBTitle -like "*Server*"}
        } else {
            $UpdateCatComponent = $UpdateCatComponent | Where-Object {$_.KBTitle -notlike "*Server*"}
        }
        $UpdateCatComponent = $UpdateCatComponent | Sort-Object -Property DatePosted

#===================================================================================================
# 18.12.03 Cumulative Updates
#===================================================================================================
        $UpdateCatCumulative = @()
        $UpdateCatCumulative = $CatalogDownloads | Where-Object {$_.Category -eq 'Cumulative'}
        $UpdateCatCumulative = $UpdateCatCumulative | Where-Object {$_.KBTitle -like "*$OSVersionNumber*"}
        $UpdateCatCumulative = $UpdateCatCumulative | Where-Object {$_.KBTitle -like "*$OSArchitecture*"}
        if ($OSInstallationType -like "*Server*") {
            $UpdateCatCumulative = $UpdateCatCumulative | Where-Object {$_.KBTitle -like "*Server*"}
        } else {
            $UpdateCatCumulative = $UpdateCatCumulative | Where-Object {$_.KBTitle -notlike "*Server*"}
        }
        $UpdateCatCumulative = $UpdateCatCumulative | Sort-Object -Property DatePosted | Select-Object -Last 1

#===================================================================================================
# 18.12.03 Servicing Stacks
#===================================================================================================
        $UpdateCatServicing = @()
        $UpdateCatServicing = $CatalogDownloads | Where-Object {$_.Category -eq 'Servicing'}
        $UpdateCatServicing = $UpdateCatServicing | Where-Object {$_.KBTitle -like "*$OSVersionNumber*"}
        $UpdateCatServicing = $UpdateCatServicing | Where-Object {$_.KBTitle -like "*$OSArchitecture*"}
        if ($OSInstallationType -like "*Server*") {
            $UpdateCatServicing = $UpdateCatServicing | Where-Object {$_.KBTitle -like "*Server*"}
        } else {
            $UpdateCatServicing = $UpdateCatServicing | Where-Object {$_.KBTitle -notlike "*Server*"}
        }
        $UpdateCatServicing = $UpdateCatServicing | Sort-Object -Property DatePosted

#===================================================================================================
# 18.12.03 Setup Updates
#===================================================================================================
        $UpdateCatSetup = @()
        $UpdateCatSetup = $CatalogDownloads | Where-Object {$_.Category -eq 'Setup'}
        $UpdateCatSetup = $UpdateCatSetup | Where-Object {$_.KBTitle -like "*$OSVersionNumber*"}
        $UpdateCatSetup = $UpdateCatSetup | Where-Object {$_.KBTitle -like "*$OSArchitecture*"}
        if ($OSInstallationType -like "*Server*") {
            $UpdateCatSetup = $UpdateCatSetup | Where-Object {$_.KBTitle -like "*Server*"}
        } else {
            $UpdateCatSetup = $UpdateCatSetup | Where-Object {$_.KBTitle -notlike "*Server*"}
        }
        $UpdateCatSetup = $UpdateCatSetup | Sort-Object -Property DatePosted

#===================================================================================================
# 18.12.03 Update Validation
#===================================================================================================
        Write-Host "===================================================================================================" -ForegroundColor Cyan
        Write-Host "Updates to Apply" -ForegroundColor Cyan

        foreach ($Update in $UpdateCatAdobe) {
            $(Get-ChildItem -Path $OSBuilderContent\Updates -Directory -Recurse | Where-Object {$_.Name -eq $($Update.KBTitle)}).FullName
            if (!(Test-Path "$OSBuilderContent\Updates\*\$($Update.KBTitle)\$($Update.FileName)")) {
                if ($DownloadUpdates.IsPresent) {
                    Write-Warning "Missing $($Update.KBTitle) ... Downloading"
                    Get-OSBuilderUpdates -FilterKBTitle "$($Update.KBTitle)" -Download -HideDetails
                } else {
                    Write-Warning "Missing $($Update.KBTitle) ... Execution will be Disabled"
                    $Execute = $false
                }
            }
        }

        foreach ($Update in $UpdateCatComponent) {
            $(Get-ChildItem -Path $OSBuilderContent\Updates -Directory -Recurse | Where-Object {$_.Name -eq $($Update.KBTitle)}).FullName
            if (!(Test-Path "$OSBuilderContent\Updates\*\$($Update.KBTitle)\$($Update.FileName)")) {
                if ($DownloadUpdates.IsPresent) {
                    Write-Warning "Missing $($Update.KBTitle) ... Downloading"
                    Get-OSBuilderUpdates -FilterKBTitle "$($Update.KBTitle)" -Download -HideDetails
                } else {
                    Write-Warning "Missing $($Update.KBTitle) ... Execution will be Disabled"
                    $Execute = $false
                }
            }
        }

        foreach ($Update in $UpdateCatCumulative) {
            $(Get-ChildItem -Path $OSBuilderContent\Updates -Directory -Recurse | Where-Object {$_.Name -eq $($Update.KBTitle)}).FullName
            if (!(Test-Path "$OSBuilderContent\Updates\*\$($Update.KBTitle)\$($Update.FileName)")) {
                if ($DownloadUpdates.IsPresent) {
                    Write-Warning "Missing $($Update.KBTitle) ... Downloading"
                    Get-OSBuilderUpdates -FilterKBTitle "$($Update.KBTitle)" -Download -HideDetails
                } else {
                    Write-Warning "Missing $($Update.KBTitle) ... Execution will be Disabled"
                    $Execute = $false
                }
            }
        }

        foreach ($Update in $UpdateCatServicing) {
            $(Get-ChildItem -Path $OSBuilderContent\Updates -Directory -Recurse | Where-Object {$_.Name -eq $($Update.KBTitle)}).FullName
            if (!(Test-Path "$OSBuilderContent\Updates\*\$($Update.KBTitle)\$($Update.FileName)")) {
                if ($DownloadUpdates.IsPresent) {
                    Write-Warning "Missing $($Update.KBTitle) ... Downloading"
                    Get-OSBuilderUpdates -FilterKBTitle "$($Update.KBTitle)" -Download -HideDetails
                } else {
                    Write-Warning "Missing $($Update.KBTitle) ... Execution will be Disabled"
                    $Execute = $false
                }
            }
        }

        foreach ($Update in $UpdateCatSetup) {
            $(Get-ChildItem -Path $OSBuilderContent\Updates -Directory -Recurse | Where-Object {$_.Name -eq $($Update.KBTitle)}).FullName
            if (!(Test-Path "$OSBuilderContent\Updates\*\$($Update.KBTitle)\$($Update.FileName)")) {
                if ($DownloadUpdates.IsPresent) {
                    Write-Warning "Missing $($Update.KBTitle) ... Downloading"
                    Get-OSBuilderUpdates -FilterKBTitle "$($Update.KBTitle)" -Download -HideDetails
                } else {
                    Write-Warning "Missing $($Update.KBTitle) ... Execution will be Disabled"
                    $Execute = $false
                }
            }
        }

#===================================================================================================
# 18.12.03 Execute
#===================================================================================================
        if ($Execute.IsPresent) {
            $Info = Join-Path $WorkingPath 'info'
            $LogsJS = Join-Path $Info 'json'
            $LogsXML = Join-Path $Info 'xml'
            $Logs =    Join-Path $Info "logs"
            if (!(Test-Path "$Info"))        {New-Item "$Info" -ItemType Directory -Force | Out-Null}
            if (!(Test-Path "$LogsJS"))        {New-Item "$LogsJS" -ItemType Directory -Force | Out-Null}
            if (!(Test-Path "$LogsXML"))    {New-Item "$LogsXML" -ItemType Directory -Force | Out-Null}
            if (!(Test-Path "$Logs"))        {New-Item "$Logs" -ItemType Directory -Force | Out-Null}

            $OS = Join-Path $WorkingPath "OS"
            $WinPE = Join-Path $WorkingPath "WinPE"
            if (!(Test-Path "$OS"))            {New-Item "$OS" -ItemType Directory -Force | Out-Null}
            if (!(Test-Path "$WinPE"))        {New-Item "$WinPE" -ItemType Directory -Force | Out-Null}

            $PEInfo = Join-Path $WinPE 'info'
            $PELogsJS = Join-Path $PEInfo 'json'
            $PELogsXML = Join-Path $PEInfo 'xml'
            $PELogs =    Join-Path $PEInfo "logs"

            if (!(Test-Path "$PEInfo"))        {New-Item "$PEInfo" -ItemType Directory -Force | Out-Null}
            if (!(Test-Path "$PELogsJS"))    {New-Item "$PELogsJS" -ItemType Directory -Force | Out-Null}
            if (!(Test-Path "$PELogsXML"))    {New-Item "$PELogsXML" -ItemType Directory -Force | Out-Null}
            if (!(Test-Path "$PELogs"))        {New-Item "$PELogs" -ItemType Directory -Force | Out-Null}

            $WimTemp = Join-Path $WorkingPath "WimTemp"
            if (!(Test-Path "$WimTemp"))    {New-Item "$WimTemp" -ItemType Directory -Force | Out-Null}

#===================================================================================================
# 18.12.03 Start the Transcript
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Starting Transcript" -ForegroundColor Cyan
            $ScriptName = $MyInvocation.MyCommand.Name
            $LogName = "$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-$ScriptName.log"
            Start-Transcript -Path (Join-Path $Logs $LogName)

#===================================================================================================
# 18.12.03 Display Build Paths
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Creating $BuildName" -ForegroundColor Cyan
            Write-Host "Working Path: $WorkingPath" -ForegroundColor Cyan
            Write-Host "-Info: $Info" -ForegroundColor Cyan
            Write-Host "-Logs: $Logs" -ForegroundColor Cyan
            Write-Host "-OS: $OS" -ForegroundColor Cyan
            Write-Host "-WinPE: $WinPE" -ForegroundColor Cyan

#===================================================================================================
# 18.12.03 Create Mount Directories
#===================================================================================================
            $MountDirectory = Join-Path $OSBuilderContent\Mount "os$((Get-Date).ToString('mmss'))"
            if ( ! (Test-Path "$MountDirectory")) {New-Item "$MountDirectory" -ItemType Directory -Force | Out-Null}
            $MountWinPE = Join-Path $OSBuilderContent\Mount "winpe$((Get-Date).ToString('mmss'))"
            if ( ! (Test-Path "$MountWinPE")) {New-Item "$MountWinPE" -ItemType Directory -Force | Out-Null}
            $MountSetup = Join-Path $OSBuilderContent\Mount "setup$((Get-Date).ToString('mmss'))"
            if ( ! (Test-Path "$MountSetup")) {New-Item "$MountSetup" -ItemType Directory -Force | Out-Null}
            $MountWinRE = Join-Path $OSBuilderContent\Mount "winre$((Get-Date).ToString('mmss'))"
            if ( ! (Test-Path "$MountWinRE")) {New-Item "$MountWinRE" -ItemType Directory -Force | Out-Null}

#===================================================================================================
# 18.12.03 Copy OS
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Media Phase: Copy Operating System" -ForegroundColor Cyan
            $WorkingPath
            Copy-Item -Path "$OSSourcePath\*" -Destination "$WorkingPath" -Exclude ('*.wim','*.iso') -Recurse -Force | Out-Null
            if (Test-Path "$WorkingPath\ISO") {Remove-Item -Path "$WorkingPath\ISO" -Force -Recurse | Out-Null}
            Copy-Item -Path "$OSSourcePath\OS\sources\install.wim" -Destination "$WimTemp\install.wim" -Force | Out-Null
            Copy-Item -Path "$OSSourcePath\WinPE\*.wim" -Destination "$WimTemp" -Exclude boot.wim -Force | Out-Null

#===================================================================================================
# 18.12.03 Setup Update
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Media Phase: Setup Update" -ForegroundColor Cyan
            if (!($null -eq $UpdateCatSetup)) {
                foreach ($Update in $UpdateCatSetup) {
                    $UpdateCatSetup = $(Get-ChildItem -Path $OSBuilderContent\Updates -File -Recurse | Where-Object {$_.Name -eq $($Update.FileName)}).FullName
                    $UpdateCatSetup
                    if (Test-Path "$UpdateCatSetup") {
                        expand.exe "$UpdateCatSetup" -F:*.* "$OS\Sources"
                    } else {
                        Write-Warning "Not Found: $UpdateCatSetup ... Skipping Update"
                    }
                }
            }

#===================================================================================================
# 18.12.03 WinPE Phase: Mount
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "WinPE Phase: Mount WIMs" -ForegroundColor Cyan

            $MountSetup
            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Mount-WindowsImage-setup.wim.log"
            Write-Host "$CurrentLog" -ForegroundColor DarkGray
            Mount-WindowsImage -ImagePath "$WimTemp\setup.wim" -Index 1 -Path "$MountSetup" -LogPath "$CurrentLog" | Out-Null

            $MountWinPE
            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Mount-WindowsImage-winpe.wim.log"
            Write-Host "$CurrentLog" -ForegroundColor DarkGray
            Mount-WindowsImage -ImagePath "$WimTemp\winpe.wim" -Index 1 -Path "$MountWinPE" -LogPath "$CurrentLog" | Out-Null

            $MountWinRE
            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Mount-WindowsImage-winre.wim.log"
            Write-Host "$CurrentLog" -ForegroundColor DarkGray
            Mount-WindowsImage -ImagePath "$WimTemp\winre.wim" -Index 1 -Path "$MountWinRE" -LogPath "$CurrentLog" | Out-Null

#===================================================================================================
# 18.12.03 WinPE Phase: Servicing Update
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "WinPE Phase: Servicing Stack Update" -ForegroundColor Cyan

            if (!($null -eq $UpdateCatServicing)) {
                foreach ($Update in $UpdateCatServicing) {
                    $UpdateSSU = $(Get-ChildItem -Path $OSBuilderContent\Updates -Directory -Recurse | Where-Object {$_.Name -eq $($Update.KBTitle)}).FullName
                    if (Test-Path "$UpdateSSU") {
                        Write-Host "$UpdateSSU"

                        if (Get-WindowsPackage -Path "$MountSetup" | Where-Object {$_.PackageName -like "*$($Update.KBNumber)*"}) {
                            Write-Warning "Setup.wim KB$($Update.KBNumber) is already installed"
                        } else {
                            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-UpdateServicing-KB$($Update.KBNumber)-setup.wim.log"
                            Write-Host "$CurrentLog" -ForegroundColor DarkGray
                            Add-WindowsPackage -Path "$MountSetup" -PackagePath "$UpdateSSU" -LogPath "$CurrentLog" | Out-Null
                        }

                        if (Get-WindowsPackage -Path "$MountWinPE" | Where-Object {$_.PackageName -like "*$($Update.KBNumber)*"}) {
                            Write-Warning "WinPE.wim KB$($Update.KBNumber) is already installed"
                        } else {
                            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-UpdateServicing-KB$($Update.KBNumber)-winpe.wim.log"
                            Write-Host "$CurrentLog" -ForegroundColor DarkGray
                            Add-WindowsPackage -Path "$MountWinPE" -PackagePath "$UpdateSSU" -LogPath "$CurrentLog" | Out-Null
                        }

                        if (Get-WindowsPackage -Path "$MountWinRE" | Where-Object {$_.PackageName -like "*$($Update.KBNumber)*"}) {
                            Write-Warning "WinRE.wim KB$($Update.KBNumber) is already installed"
                        } else {
                            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-UpdateServicing-KB$($Update.KBNumber)-winre.wim.log"
                            Write-Host "$CurrentLog" -ForegroundColor DarkGray
                            Add-WindowsPackage -Path "$MountWinRE" -PackagePath "$UpdateSSU" -LogPath "$CurrentLog" | Out-Null
                        }
                    } else {
                        Write-Warning "Not Found: $UpdateSSU ... Skipping Update"
                    }
                }
            }

#===================================================================================================
# 18.12.03 WinPE Phase: Cumulative Update
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "WinPE Phase: Cumulative Update" -ForegroundColor Cyan
            if (!($null -eq $UpdateCatCumulative)) {
                foreach ($Update in $UpdateCatCumulative) {
                    $UpdateCU = $(Get-ChildItem -Path $OSBuilderContent\Updates -Directory -Recurse | Where-Object {$_.Name -eq $($Update.KBTitle)}).FullName
                    if (Test-Path "$UpdateCU") {
                        Write-Host "$UpdateCU"

                        #if (Get-WindowsPackage -Path "$MountSetup" | Where-Object {$_.PackageName -like "*$($Update.KBNumber)*"}) {}
                        $SessionsXmlSetup = "$MountSetup\Windows\Servicing\Sessions\Sessions.xml"
                        if (Test-Path $SessionsXmlSetup) {
                            [xml]$XmlDocument = Get-Content -Path $SessionsXmlSetup
                            if ($XmlDocument.Sessions.Session.Tasks.Phase.package | Where-Object {$_.Name -like "*$($Update.KBNumber)*" -and $_.targetState -eq 'Installed'}) {
                                Write-Warning "Setup.wim KB$($Update.KBNumber) is already installed"
                            } else {
                                $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-UpdateCumulative-KB$($Update.KBNumber)-setup.wim.log"
                                Write-Host "$CurrentLog" -ForegroundColor DarkGray
                                Add-WindowsPackage -Path "$MountSetup" -PackagePath "$UpdateCU" -LogPath "$CurrentLog" | Out-Null
                                
                                $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-DismCleanupImage-setup.wim.log"
                                Write-Host "$CurrentLog" -ForegroundColor DarkGray
                                Dism /Image:"$MountSetup" /Cleanup-Image /StartComponentCleanup /ResetBase /LogPath:"$CurrentLog"
                            }
                        } else {
                            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-UpdateCumulative-KB$($Update.KBNumber)-setup.wim.log"
                            Write-Host "$CurrentLog" -ForegroundColor DarkGray
                            Add-WindowsPackage -Path "$MountSetup" -PackagePath "$UpdateCU" -LogPath "$CurrentLog" | Out-Null
                            
                            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-DismCleanupImage-setup.wim.log"
                            Write-Host "$CurrentLog" -ForegroundColor DarkGray
                            Dism /Image:"$MountSetup" /Cleanup-Image /StartComponentCleanup /ResetBase /LogPath:"$CurrentLog"
                        }

                        #if (Get-WindowsPackage -Path "$MountWinPE" | Where-Object {$_.PackageName -like "*$($Update.KBNumber)*"}) {}
                        $SessionsXmlWinPE = "$MountWinPE\Windows\Servicing\Sessions\Sessions.xml"
                        if (Test-Path $SessionsXmlWinPE) {
                            [xml]$XmlDocument = Get-Content -Path $SessionsXmlWinPE
                            if ($XmlDocument.Sessions.Session.Tasks.Phase.package | Where-Object {$_.Name -like "*$($Update.KBNumber)*" -and $_.targetState -eq 'Installed'}) {
                                Write-Warning "WinPE.wim KB$($Update.KBNumber) is already installed"
                            } else {
                                $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-UpdateCumulative-KB$($Update.KBNumber)-winpe.wim.log"
                                Write-Host "$CurrentLog" -ForegroundColor DarkGray
                                Add-WindowsPackage -Path "$MountWinPE" -PackagePath "$UpdateCU" -LogPath "$CurrentLog" | Out-Null
                                
                                $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-DismCleanupImage-winpe.wim.log"
                                Write-Host "$CurrentLog" -ForegroundColor DarkGray
                                Dism /Image:"$MountWinPE" /Cleanup-Image /StartComponentCleanup /ResetBase /LogPath:"$CurrentLog"
                            }
                        } else {
                            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-UpdateCumulative-KB$($Update.KBNumber)-winpe.wim.log"
                            Write-Host "$CurrentLog" -ForegroundColor DarkGray
                            Add-WindowsPackage -Path "$MountWinPE" -PackagePath "$UpdateCU" -LogPath "$CurrentLog" | Out-Null
                            
                            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-DismCleanupImage-winpe.wim.log"
                            Write-Host "$CurrentLog" -ForegroundColor DarkGray
                            Dism /Image:"$MountWinPE" /Cleanup-Image /StartComponentCleanup /ResetBase /LogPath:"$CurrentLog"
                        }

                        #if (Get-WindowsPackage -Path "$MountWinRE" | Where-Object {$_.PackageName -like "*$($Update.KBNumber)*"}) {}
                        $SessionsXmlWinRE = "$MountWinRE\Windows\Servicing\Sessions\Sessions.xml"
                        if (Test-Path $SessionsXmlWinRE) {
                            [xml]$XmlDocument = Get-Content -Path $SessionsXmlWinRE
                            if ($XmlDocument.Sessions.Session.Tasks.Phase.package | Where-Object {$_.Name -like "*$($Update.KBNumber)*" -and $_.targetState -eq 'Installed'}) {
                                Write-Warning "WinRE.wim KB$($Update.KBNumber) is already installed"
                            } else {
                                $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-UpdateCumulative-KB$($Update.KBNumber)-winre.wim.log"
                                Write-Host "$CurrentLog" -ForegroundColor DarkGray
                                Add-WindowsPackage -Path "$MountWinRE" -PackagePath "$UpdateCU" -LogPath "$CurrentLog" | Out-Null

                                $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-DismCleanupImage-winre.wim.log"
                                Write-Host "$CurrentLog" -ForegroundColor DarkGray
                                Dism /Image:"$MountWinRE" /Cleanup-Image /StartComponentCleanup /ResetBase /LogPath:"$CurrentLog"
                            }
                        } else {
                            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-UpdateCumulative-KB$($Update.KBNumber)-winre.wim.log"
                            Write-Host "$CurrentLog" -ForegroundColor DarkGray
                            Add-WindowsPackage -Path "$MountWinRE" -PackagePath "$UpdateCU" -LogPath "$CurrentLog" | Out-Null
                            
                            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-DismCleanupImage-winre.wim.log"
                            Write-Host "$CurrentLog" -ForegroundColor DarkGray
                            Dism /Image:"$MountWinRE" /Cleanup-Image /StartComponentCleanup /ResetBase /LogPath:"$CurrentLog"
                        }
                    } else {
                        Write-Warning "Not Found: $UpdateCU"
                    }
                }
            }

#===================================================================================================
# 18.12.03 WinPE Phase: Update Media Sources
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "WinPE Phase: Updating Media Sources with Setup.wim" -ForegroundColor Cyan
            #[void](Read-Host 'Press Enter to Continue')
            robocopy "$MountSetup\sources" "$OS\sources" setup.exe /ndl /xo /xx /xl /b /np /ts /tee /r:0 /w:0 /log:"$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Robocopy-setup.wim-MediaSources.log" | Out-Null
            robocopy "$MountSetup\sources" "$OS\sources" setuphost.exe /ndl /xo /xx /xl /b /np /ts /tee /r:0 /w:0 /log:"$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Robocopy-setup.wim-MediaSources.log" | Out-Null

#===================================================================================================
# 18.12.03 WinPE Mounted Package Inventory
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "WinPE Phase: Export Package Inventory" -ForegroundColor Cyan
            Write-Host "$PEInfo\setup-WindowsPackage.txt"
            $GetWindowsPackage = Get-WindowsPackage -Path "$MountSetup"
            $GetWindowsPackage | Out-File "$PEInfo\setup-WindowsPackage.txt"
            $GetWindowsPackage | Out-File "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsPackage-setup.wim.txt"
            $GetWindowsPackage | Export-Clixml -Path "$PELogsXML\Get-WindowsPackage-setup.wim.xml"
            $GetWindowsPackage | Export-Clixml -Path "$PELogsXML\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsPackage-setup.wim.xml"
            $GetWindowsPackage | ConvertTo-Json | Out-File "$PELogsJS\Get-WindowsPackage-setup.wim.json"
            $GetWindowsPackage | ConvertTo-Json | Out-File "$PELogsJS\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsPackage-setup.wim.json"

            Write-Host "$PEInfo\winpe-WindowsPackage.txt"
            $GetWindowsPackage = Get-WindowsPackage -Path "$MountWinPE"
            $GetWindowsPackage | Out-File "$PEInfo\winpe-WindowsPackage.txt"
            $GetWindowsPackage | Out-File "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsPackage-winpe.wim.txt"
            $GetWindowsPackage | Export-Clixml -Path "$PELogsXML\Get-WindowsPackage-winpe.wim.xml"
            $GetWindowsPackage | Export-Clixml -Path "$PELogsXML\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsPackage-winpe.wim.xml"
            $GetWindowsPackage | ConvertTo-Json | Out-File "$PELogsJS\Get-WindowsPackage-winpe.wim.json"
            $GetWindowsPackage | ConvertTo-Json | Out-File "$PELogsJS\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsPackage-winpe.wim.json"

            Write-Host "$PEInfo\winre-WindowsPackage.txt"
            $GetWindowsPackage = Get-WindowsPackage -Path "$MountWinRE"
            $GetWindowsPackage | Out-File "$PEInfo\winre-WindowsPackage.txt"
            $GetWindowsPackage | Out-File "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsPackage-winre.wim.txt"
            $GetWindowsPackage | Export-Clixml -Path "$PELogsXML\Get-WindowsPackage-winre.wim.xml"
            $GetWindowsPackage | Export-Clixml -Path "$PELogsXML\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsPackage-winre.wim.xml"
            $GetWindowsPackage | ConvertTo-Json | Out-File "$PELogsJS\Get-WindowsPackage-winre.wim.json"
            $GetWindowsPackage | ConvertTo-Json | Out-File "$PELogsJS\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsPackage-winre.wim.json"

#===================================================================================================
# 18.12.3 WinPE Dismount and Save
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "WinPE Phase: Dismount and Save" -ForegroundColor Cyan
            if ($PromptBeforeDismountWinPE.IsPresent){[void](Read-Host 'Press Enter to Continue')}

            $MountSetup
            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Dismount-WindowsImage-setup.wim.log"
            Write-Host "$CurrentLog" -ForegroundColor DarkGray
            Dismount-WindowsImage -Path "$MountSetup" -Save -LogPath "$CurrentLog" | Out-Null

            $MountWinPE
            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Dismount-WindowsImage-winpe.wim.log"
            Write-Host "$CurrentLog" -ForegroundColor DarkGray
            Dismount-WindowsImage -Path "$MountWinPE" -Save -LogPath "$CurrentLog" | Out-Null

            $MountWinRE
            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Dismount-WindowsImage-winre.wim.log"
            Write-Host "$CurrentLog" -ForegroundColor DarkGray
            Dismount-WindowsImage -Path "$MountWinRE" -Save -LogPath "$CurrentLog" | Out-Null

#===================================================================================================
# 18.12.3 Export WinPE
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "WinPE Phase: Export WinPE WIMs" -ForegroundColor Cyan

            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Export-WindowsImage-setup.wim.log"
            Write-Host "$CurrentLog" -ForegroundColor DarkGray
            Export-WindowsImage -SourceImagePath "$WimTemp\setup.wim" -SourceIndex 1 -DestinationImagePath "$WinPE\setup.wim" -LogPath "CurrentLog" | Out-Null
           
            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Export-WindowsImage-winpe.wim.log"
            Write-Host "$CurrentLog" -ForegroundColor DarkGray
            Export-WindowsImage -SourceImagePath "$WimTemp\winpe.wim" -SourceIndex 1 -DestinationImagePath "$WinPE\winpe.wim" -LogPath "CurrentLog" | Out-Null

            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Export-WindowsImage-winre.wim.log"
            Write-Host "$CurrentLog" -ForegroundColor DarkGray
            Export-WindowsImage -SourceImagePath "$WimTemp\winre.wim" -SourceIndex 1 -DestinationImagePath "$WinPE\winre.wim" -LogPath "CurrentLog" | Out-Null

#===================================================================================================
# 18.12.3 Rebuild Boot.wim
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "WinPE Phase: Rebuild $OS\sources\boot.wim" -ForegroundColor Cyan

            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Export-WindowsImage-winpe.wim.log"
            Write-Host "$CurrentLog" -ForegroundColor DarkGray
            Export-WindowsImage -SourceImagePath "$WimTemp\winpe.wim" -SourceIndex 1 -DestinationImagePath "$WinPE\boot.wim" -LogPath "$CurrentLog" | Out-Null
            
            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Export-WindowsImage-setup.wim.log"
            Write-Host "$CurrentLog" -ForegroundColor DarkGray
            Export-WindowsImage -SourceImagePath "$WimTemp\setup.wim" -SourceIndex 1 -DestinationImagePath "$WinPE\boot.wim" -Setbootable -LogPath "$CurrentLog" | Out-Null
            
            Copy-Item -Path "$WinPE\boot.wim" -Destination "$OS\sources\boot.wim" -Force | Out-Null

#===================================================================================================
# 18.12.3 Mount Install.wim
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Install.wim Phase: Mount Operating System" -ForegroundColor Cyan
            Write-Host $MountDirectory

            $CurrentLog = "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Mount-WindowsImage.log"
            Write-Host "$CurrentLog" -ForegroundColor DarkGray
            Mount-WindowsImage -ImagePath "$WimTemp\install.wim" -Index 1 -Path "$MountDirectory" -LogPath "$CurrentLog" | Out-Null

#===================================================================================================
# 18.12.3 Get Registry and UBR
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Mounting Registry for UBR Information" -ForegroundColor Cyan

            reg LOAD 'HKLM\OSMedia' "$MountDirectory\Windows\System32\Config\SOFTWARE" | Out-Null
            $RegCurrentVersion = Get-ItemProperty -Path 'HKLM:\OSMedia\Microsoft\Windows NT\CurrentVersion'
            reg UNLOAD 'HKLM\OSMedia' | Out-Null

            $OSVersionNumber = $null
            $OSVersionNumber = $($RegCurrentVersion.ReleaseId)
            $RegCurrentVersionUBR = $($RegCurrentVersion.UBR)
            $UBR = "$OSBuild.$RegCurrentVersionUBR"

            $RegCurrentVersion | Out-File "$Info\CurrentVersion.txt"
            $RegCurrentVersion | Out-File "$WorkingPath\CurrentVersion.txt"
            $RegCurrentVersion | Out-File "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-CurrentVersion.txt"
            $RegCurrentVersion | Export-Clixml -Path "$LogsXML\CurrentVersion.xml"
            $RegCurrentVersion | Export-Clixml -Path "$LogsXML\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-CurrentVersion.xml"
            $RegCurrentVersion | ConvertTo-Json | Out-File "$LogsJS\CurrentVersion.json"
            $RegCurrentVersion | ConvertTo-Json | Out-File "$LogsJS\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-CurrentVersion.json"

#===================================================================================================
# 18.12.3 Replace WinRE
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Install.wim Phase: Replace WinRE.wim" -ForegroundColor Cyan
            if (Test-Path "$MountDirectory\Windows\System32\Recovery\winre.wim") {
                Remove-Item -Path "$MountDirectory\Windows\System32\Recovery\winre.wim" -Force
            }

            Copy-Item -Path "$WinPE\winre.wim" -Destination "$MountDirectory\Windows\System32\Recovery\winre.wim" -Force | Out-Null

            $GetWindowsImage = Get-WindowsImage -ImagePath "$WinPE\winre.wim" -Index 1 | Select-Object -Property *
            $GetWindowsImage | Out-File "$PEInfo\winre.txt"
            (Get-Content "$PEInfo\winre.txt") | Where-Object {$_.Trim(" `t")} | Set-Content "$PEInfo\winre.txt"
            $GetWindowsImage | Out-File "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsImage-winre.wim.txt"
            $GetWindowsImage | Export-Clixml -Path "$PELogsXML\Get-WindowsImage-winre.wim.xml"
            $GetWindowsImage | Export-Clixml -Path "$PELogsXML\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsImage-winre.wim.xml"
            $GetWindowsImage | ConvertTo-Json | Out-File "$PELogsJS\Get-WindowsImage-winre.wim.json"
            $GetWindowsImage | ConvertTo-Json | Out-File "$PELogsJS\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsImage-winre.wim.json"

#===================================================================================================
# 18.12.3 Install.wim Servicing Update
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Install.wim Phase: Servicing Update" -ForegroundColor Cyan
            if (!($null -eq $UpdateCatServicing)) {
                foreach ($Update in $UpdateCatServicing) {
                    $UpdateSSU = $(Get-ChildItem -Path $OSBuilderContent\Updates -Directory -Recurse | Where-Object {$_.Name -eq $($Update.KBTitle)}).FullName
                    if (Test-Path "$UpdateSSU") {
                        Write-Host "$UpdateSSU"
                        if (Get-WindowsPackage -Path "$MountDirectory" | Where-Object {$_.PackageName -like "*$($Update.KBNumber)*"}) {
                            Write-Warning "KB$($Update.KBNumber) is already installed"
                        } else {
                            $CurrentLog = "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-UpdateServicing-KB$($Update.KBNumber)-install.wim.log"
                            Write-Host "$CurrentLog" -ForegroundColor DarkGray
                            Add-WindowsPackage -Path "$MountDirectory" -PackagePath "$UpdateSSU" -LogPath "$CurrentLog" | Out-Null
                        }
                    } else {
                        Write-Warning "Not Found: $UpdateSSU"
                    }
                }
            }

#===================================================================================================
# 18.12.3 Install.wim Component Update
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Install.wim Phase: Component Update" -ForegroundColor Cyan
            if (!($null -eq $UpdateCatComponent)) {
                foreach ($Update in $UpdateCatComponent) {
                    $UpdateComp = $(Get-ChildItem -Path $OSBuilderContent\Updates -Directory -Recurse | Where-Object {$_.Name -eq $($Update.KBTitle)}).FullName
                    if (Test-Path "$UpdateComp") {
                        Write-Host "$UpdateComp"
                        if (Get-WindowsPackage -Path "$MountDirectory" | Where-Object {$_.PackageName -like "*$($Update.KBNumber)*"}) {
                            Write-Warning "KB$($Update.KBNumber) is already installed"
                        } else {
                            $CurrentLog = "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-UpdateComponent-KB$($Update.KBNumber)-install.wim.log"
                            Write-Host "$CurrentLog" -ForegroundColor DarkGray
                            Add-WindowsPackage -Path "$MountDirectory" -PackagePath "$UpdateComp" -LogPath "$CurrentLog" | Out-Null
                        }
                    } else {
                        Write-Warning "Not Found: $UpdateComp"
                    }
                }
            }

#===================================================================================================
# 18.12.03 Get UBR (Pre Windows Updates)
#===================================================================================================
            $UBRPre = $UBR
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Install.wim Phase: Update Build Revision $UBRPre (Pre-Windows Updates)"    -ForegroundColor Cyan

#===================================================================================================
# 18.12.03 Install.wim Cumulative Update
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Install.wim Phase: Cumulative Update" -ForegroundColor Cyan
            if (!($null -eq $UpdateCatCumulative)) {
                foreach ($Update in $UpdateCatCumulative) {
                    $UpdateCU = $(Get-ChildItem -Path $OSBuilderContent\Updates -Directory -Recurse | Where-Object {$_.Name -eq $($Update.KBTitle)}).FullName
                    if (Test-Path "$UpdateCU") {
                        Write-Host "$UpdateCU"
                        $SessionsXmlInstall = "$MountDirectory\Windows\Servicing\Sessions\Sessions.xml"
                        if (Test-Path $SessionsXmlInstall) {
                            [xml]$XmlDocument = Get-Content -Path $SessionsXmlInstall
                            if ($XmlDocument.Sessions.Session.Tasks.Phase.package | Where-Object {$_.Name -like "*$($Update.KBNumber)*" -and $_.targetState -eq 'Installed'}) {
                                Write-Warning "KB$($Update.KBNumber) is already installed"
                            } else {
                                Add-WindowsPackage -Path "$MountDirectory" -PackagePath "$UpdateCU" -LogPath "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-UpdateCumulative-KB$($Update.KBNumber)-install.wim.log"
                            }
                        } else {
                            $CurrentLog = "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-UpdateCumulative-KB$($Update.KBNumber)-install.wim.log"
                            Write-Host "$CurrentLog" -ForegroundColor DarkGray
                            Add-WindowsPackage -Path "$MountDirectory" -PackagePath "$UpdateCU" -LogPath "$CurrentLog" | Out-Null
                        }
                    } else {
                        Write-Warning "Not Found: $UpdateCU"
                    }
                }
            }

#===================================================================================================
# 18.12.03 Get Registry and UBR
#===================================================================================================
            #Write-Host "===================================================================================================" -ForegroundColor Cyan
            #Write-Host "Install.wim Phase: Registry Postinstall" -ForegroundColor Cyan
            reg LOAD 'HKLM\OSMedia' "$MountDirectory\Windows\System32\Config\SOFTWARE" | Out-Null
            $RegCurrentVersion = Get-ItemProperty -Path 'HKLM:\OSMedia\Microsoft\Windows NT\CurrentVersion'
            reg UNLOAD 'HKLM\OSMedia' | Out-Null

            $OSVersionNumber = $null
            $OSVersionNumber = $($RegCurrentVersion.ReleaseId)
            $RegCurrentVersionUBR = $($RegCurrentVersion.UBR)
            $UBR = "$OSBuild.$RegCurrentVersionUBR"

            $RegCurrentVersion | Out-File "$Info\CurrentVersion.txt"
            $RegCurrentVersion | Out-File "$WorkingPath\CurrentVersion.txt"
            $RegCurrentVersion | Out-File "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-CurrentVersion.txt"
            $RegCurrentVersion | Export-Clixml -Path "$LogsXML\CurrentVersion.xml"
            $RegCurrentVersion | Export-Clixml -Path "$LogsXML\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-CurrentVersion.xml"
            $RegCurrentVersion | ConvertTo-Json | Out-File "$LogsJS\CurrentVersion.json"
            $RegCurrentVersion | ConvertTo-Json | Out-File "$LogsJS\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-CurrentVersion.json"

#===================================================================================================
# 18.12.03 Get UBR (Post Windows Updates)
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Install.wim Phase: Update Build Revision $UBR (Post-Windows Updates)"    -ForegroundColor Cyan

#===================================================================================================
# 18.12.03 Install.wim Adobe Update
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Install.wim Phase: Adobe Update" -ForegroundColor Cyan
            if (!($null -eq $UpdateCatAdobe)) {
                foreach ($Update in $UpdateCatAdobe) {
                    $UpdateA = $(Get-ChildItem -Path $OSBuilderContent\Updates -Directory -Recurse | Where-Object {$_.Name -eq $($Update.KBTitle)}).FullName
                    if (Test-Path "$UpdateA") {
                        Write-Host "$UpdateA"
                        if (Get-WindowsPackage -Path "$MountDirectory" | Where-Object {$_.PackageName -like "*$($Update.KBNumber)*"}) {
                            Write-Warning "KB$($Update.KBNumber) is already installed"
                        } else {
                            $CurrentLog = "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-UpdateAdobe-KB$($Update.KBNumber)-install.wim.log"
                            Write-Host "$CurrentLog" -ForegroundColor DarkGray
                            Add-WindowsPackage -Path "$MountDirectory" -PackagePath "$UpdateA" -LogPath "$CurrentLog" | Out-Null
                        }
                    } else {
                        Write-Warning "Not Found: $UpdateA"
                    }
                }
            }

#===================================================================================================
# 18.12.03 Install.wim Image Cleanup
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Install.wim Phase: Windows Image Cleanup" -ForegroundColor Cyan
            if ($(Get-WindowsCapability -Path $MountDirectory | Where-Object {$_.state -eq "*pending*"})) {
                Write-Warning "Cannot run WindowsImage Cleanup on a WIM with Pending Installations"
            } else {
                $CurrentLog = "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Dism-Cleanup-Image.log"
                Write-Host "$CurrentLog" -ForegroundColor DarkGray
                Dism /Image:"$MountDirectory" /Cleanup-Image /StartComponentCleanup /ResetBase /LogPath:"$CurrentLog"
            }

#===================================================================================================
# 18.12.03 Auto ExtraFiles
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Install.wim Phase: Collect Auto ExtraFiles" -ForegroundColor Cyan
            $AEFLogs = "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Robocopy-AutoExtraFiles.log"
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" cacls.exe* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" choice.exe* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            #robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" cleanmgr.exe* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" comp.exe*.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" defrag*.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" djoin*.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" forfiles*.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" getmac*.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" makecab.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" msinfo32.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" nslookup.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" systeminfo.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" tskill.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" winver.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            # AeroLite Theme
            robocopy "$MountDirectory\Windows\Resources" "$WorkingPath\WinPE\AutoExtraFiles\Windows\Resources" aerolite*.* /s /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\Resources" "$WorkingPath\WinPE\AutoExtraFiles\Windows\Resources" shellstyle*.* /s /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            # Magnify
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" magnify*.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" magnification*.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            # On Screen Keyboard
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" osk*.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            # RDP
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" mstsc*.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" pdh.dll* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" srpapi.dll* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            # Shutdown
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" shutdown.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" shutdownext.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" shutdownux.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            # Browse Dialog 18.10.31
            robocopy "$MountDirectory\Windows\Resources\Themes\aero\shell\normalcolor" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" shellstyle*.* /s /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" explorerframe*.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" StructuredQuery*.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" edputil*.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            # Wireless 18.10.31
            # http://www.scconfigmgr.com/2018/03/06/build-a-winpe-with-wireless-support/
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" dmcmnutils*.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" mdmregistration*.* /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null
            # BPC47
            robocopy "$MountDirectory\Windows\System32" "$WorkingPath\WinPE\AutoExtraFiles\Windows\System32" bpc47*.dll /s /xd rescache servicing /ndl /b /np /ts /tee /r:0 /w:0 /log+:"$AEFLogs" | Out-Null

        #===================================================================================================
        # 18.12.19 Export Sessions.xml
        #===================================================================================================
        Write-Host "===================================================================================================" -ForegroundColor Cyan
        Write-Host "Install.wim Phase: Export Sessions.xml" -ForegroundColor Cyan
        if (Test-Path "$MountDirectory\Windows\Servicing\Sessions\Sessions.xml") {
            Copy-Item "$MountDirectory\Windows\Servicing\Sessions\Sessions.xml" "$OSMediaPath\Sessions.xml" -Force | Out-Null
        }
        if (Test-Path "$MountDirectory\Windows\Servicing\Sessions\ActionList.xml") {
            Copy-Item "$MountDirectory\Windows\Servicing\Sessions\ActionList.xml" "$OSMediaPath\ActionList.xml" -Force | Out-Null
        }

#===================================================================================================
# 18.12.03 Install.wim Save Mounted Windows Image Configuration
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Install.wim Phase: Saving Mounted Windows Image Configuration" -ForegroundColor Cyan

            $GetAppxProvisionedPackage = @()
            Write-Host "$WorkingPath\AppxProvisionedPackage.txt"
            try {$GetAppxProvisionedPackage = Get-AppxProvisionedPackage -Path "$MountDirectory"}
            catch {Write-Warning "Get-AppxProvisionedPackage is not supported by this Operating System"}
            $GetAppxProvisionedPackage | Out-File "$Info\Get-AppxProvisionedPackage.txt"
            $GetAppxProvisionedPackage | Out-File "$WorkingPath\AppxProvisionedPackage.txt"
            $GetAppxProvisionedPackage | Out-File "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-AppxProvisionedPackage.txt"
            $GetAppxProvisionedPackage | Export-Clixml -Path "$LogsXML\Get-AppxProvisionedPackage.xml"
            $GetAppxProvisionedPackage | Export-Clixml -Path "$LogsXML\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-AppxProvisionedPackage.xml"
            $GetAppxProvisionedPackage | ConvertTo-Json | Out-File "$LogsJS\Get-AppxProvisionedPackage.json"
            $GetAppxProvisionedPackage | ConvertTo-Json | Out-File "$LogsJS\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-AppxProvisionedPackage.json"
                
            Write-Host "$WorkingPath\WindowsOptionalFeature.txt"
            $GetWindowsOptionalFeature = Get-WindowsOptionalFeature -Path "$MountDirectory"
            $GetWindowsOptionalFeature | Out-File "$Info\Get-WindowsOptionalFeature.txt"
            $GetWindowsOptionalFeature | Out-File "$WorkingPath\WindowsOptionalFeature.txt"
            $GetWindowsOptionalFeature | Out-File "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsOptionalFeature.txt"
            $GetWindowsOptionalFeature | Export-Clixml -Path "$LogsXML\Get-WindowsOptionalFeature.xml"
            $GetWindowsOptionalFeature | Export-Clixml -Path "$LogsXML\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsOptionalFeature.xml"
            $GetWindowsOptionalFeature | ConvertTo-Json | Out-File "$LogsJS\Get-WindowsOptionalFeature.json"
            $GetWindowsOptionalFeature | ConvertTo-Json | Out-File "$LogsJS\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsOptionalFeature.json"

            Write-Host "$WorkingPath\WindowsCapability.txt"
            $GetWindowsCapability = Get-WindowsCapability -Path "$MountDirectory"
            $GetWindowsCapability | Out-File "$Info\Get-WindowsCapability.txt"
            $GetWindowsCapability | Out-File "$WorkingPath\WindowsCapability.txt"
            $GetWindowsCapability | Out-File "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsCapability.txt"
            $GetWindowsCapability | Export-Clixml -Path "$LogsXML\Get-WindowsCapability.xml"
            $GetWindowsCapability | Export-Clixml -Path "$LogsXML\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsCapability.xml"
            $GetWindowsCapability | ConvertTo-Json | Out-File "$LogsJS\Get-WindowsCapability.json"
            $GetWindowsCapability | ConvertTo-Json | Out-File "$LogsJS\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsCapability.json"

            Write-Host "$WorkingPath\WindowsPackage.txt"
            $GetWindowsPackage = Get-WindowsPackage -Path "$MountDirectory"
            $GetWindowsPackage | Out-File "$Info\Get-WindowsPackage.txt"
            $GetWindowsPackage | Out-File "$WorkingPath\WindowsPackage.txt"
            $GetWindowsPackage | Out-File "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsPackage.txt"
            $GetWindowsPackage | Export-Clixml -Path "$LogsXML\Get-WindowsPackage.xml"
            $GetWindowsPackage | Export-Clixml -Path "$LogsXML\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsPackage.xml"
            $GetWindowsPackage | ConvertTo-Json | Out-File "$LogsJS\Get-WindowsPackage.json"
            $GetWindowsPackage | ConvertTo-Json | Out-File "$LogsJS\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsPackage.json"

#===================================================================================================
# 18.12.03 Dismount and Save
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Install.wim Phase: Dismount and Save" -ForegroundColor Cyan
            if ($PromptBeforeDismount.IsPresent){[void](Read-Host 'Press Enter to Continue')}

            $CurrentLog = "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Dismount-WindowsImage.log"
            Write-Host "$CurrentLog" -ForegroundColor DarkGray
            Dismount-WindowsImage -Path "$MountDirectory" -Save -LogPath "$CurrentLog" | Out-Null

#===================================================================================================
# 18.12.03 Export Install.wim
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Install.wim Phase: Export Install.wim" -ForegroundColor Cyan

            $CurrentLog = "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Export-WindowsImage.log"
            Write-Host "$CurrentLog" -ForegroundColor DarkGray
            Export-WindowsImage -SourceImagePath "$WimTemp\install.wim" -SourceIndex 1 -DestinationImagePath "$OS\sources\install.wim" -LogPath "$CurrentLog" | Out-Null

#===================================================================================================
# 18.12.04 Get-WindowsImage Boot.wim
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Media Phase: Save WinPE Image Configuration" -ForegroundColor Cyan

#===================================================================================================
# 18.12.03 Get-WindowsImage Boot.wim
#===================================================================================================
            Write-Host "$PEInfo\boot.txt"
            $GetWindowsImage = Get-WindowsImage -ImagePath "$OS\sources\boot.wim"
            $GetWindowsImage | Out-File "$PEInfo\boot.txt"
            (Get-Content "$PEInfo\boot.txt") | Where-Object {$_.Trim(" `t")} | Set-Content "$PEInfo\boot.txt"
            $GetWindowsImage | Out-File "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsImage-boot.wim.txt"
            $GetWindowsImage | Export-Clixml -Path "$PELogsXML\Get-WindowsImage-boot.wim.xml"
            $GetWindowsImage | Export-Clixml -Path "$PELogsXML\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsImage-boot.wim.xml"
            $GetWindowsImage | ConvertTo-Json | Out-File "$PELogsJS\Get-WindowsImage-boot.wim.json"
            $GetWindowsImage | ConvertTo-Json | Out-File "$PELogsJS\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsImage-boot.wim.json"

#===================================================================================================
# 18.12.04 Get-WindowsImage WinPE
#===================================================================================================
            Write-Host "$PEInfo\winpe.txt"
            $GetWindowsImage = Get-WindowsImage -ImagePath "$OS\sources\boot.wim" -Index 1 | Select-Object -Property *
            $GetWindowsImage | Out-File "$PEInfo\winpe.txt"
            (Get-Content "$PEInfo\winpe.txt") | Where-Object {$_.Trim(" `t")} | Set-Content "$PEInfo\winpe.txt"
            $GetWindowsImage | Out-File "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsImage-winpe.wim.txt"
            $GetWindowsImage | Export-Clixml -Path "$PELogsXML\Get-WindowsImage-winpe.wim.xml"
            $GetWindowsImage | Export-Clixml -Path "$PELogsXML\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsImage-winpe.wim.xml"
            $GetWindowsImage | ConvertTo-Json | Out-File "$PELogsJS\Get-WindowsImage-winpe.wim.json"
            $GetWindowsImage | ConvertTo-Json | Out-File "$PELogsJS\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsImage-winpe.wim.json"

#===================================================================================================
# 18.12.04 Get-WindowsImage Setup
#===================================================================================================
            Write-Host "$PEInfo\setup.txt"
            $GetWindowsImage = Get-WindowsImage -ImagePath "$OS\sources\boot.wim" -Index 2 | Select-Object -Property *
            $GetWindowsImage | Out-File "$PEInfo\setup.txt"
            (Get-Content "$PEInfo\setup.txt") | Where-Object {$_.Trim(" `t")} | Set-Content "$PEInfo\setup.txt"
            $GetWindowsImage | Out-File "$PELogs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsImage-setup.wim.txt"
            $GetWindowsImage | Export-Clixml -Path "$PELogsXML\Get-WindowsImage-setup.wim.xml"
            $GetWindowsImage | Export-Clixml -Path "$PELogsXML\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsImage-setup.wim.xml"
            $GetWindowsImage | ConvertTo-Json | Out-File "$PELogsJS\Get-WindowsImage-setup.wim.json"
            $GetWindowsImage | ConvertTo-Json | Out-File "$PELogsJS\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsImage-setup.wim.json"

#===================================================================================================
# 18.12.04 Export Windows Image Configuration
#===================================================================================================
        Write-Host "===================================================================================================" -ForegroundColor Cyan
        Write-Host "Media Phase: Export Windows Image Configuration" -ForegroundColor Cyan
        Write-Host "$WorkingPath\WindowsImage.txt"
        $GetWindowsImage = Get-WindowsImage -ImagePath "$OS\sources\install.wim" -Index 1 | Select-Object -Property *
        $GetWindowsImage | Add-Member -Type NoteProperty -Name "UBR" -Value $UBR
        $GetWindowsImage | Out-File "$WorkingPath\WindowsImage.txt"
        $GetWindowsImage | Out-File "$Logs\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsImage.txt"
        $GetWindowsImage | Export-Clixml -Path "$LogsXML\Get-WindowsImage.xml"
        $GetWindowsImage | Export-Clixml -Path "$LogsXML\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsImage.xml"
        $GetWindowsImage | ConvertTo-Json | Out-File "$LogsJS\Get-WindowsImage.json"
        $GetWindowsImage | ConvertTo-Json | Out-File "$LogsJS\$((Get-Date).ToString('yyyy-MM-dd-HHmmss'))-Get-WindowsImage.json"
        (Get-Content "$WorkingPath\WindowsImage.txt") | Where-Object {$_.Trim(" `t")} | Set-Content "$WorkingPath\WindowsImage.txt"

#===================================================================================================
# 18.12.04 Get-WindowsImageContent
#===================================================================================================
        Write-Host "$Info\Get-WindowsImageContent.txt"
        Get-WindowsImageContent -ImagePath "$OS\Sources\install.wim" -Index 1 | Out-File "$Info\Get-WindowsImageContent.txt"

#===================================================================================================
# 18.12.04 Display OS Information
#===================================================================================================
        Show-OSInfo $WorkingPath

#===================================================================================================
# 18.12.03 Remove Temporary Files
#===================================================================================================
            if (Test-Path "$WimTemp") {Remove-Item -Path "$WimTemp" -Force -Recurse | Out-Null}
            if (Test-Path "$MountDirectory") {Remove-Item -Path "$MountDirectory" -Force -Recurse | Out-Null}
            if (Test-Path "$MountWinRE") {Remove-Item -Path "$MountWinRE" -Force -Recurse | Out-Null}
            if (Test-Path "$MountWinPE") {Remove-Item -Path "$MountWinPE" -Force -Recurse | Out-Null}
            if (Test-Path "$MountSetup") {Remove-Item -Path "$MountSetup" -Force -Recurse | Out-Null}
            
#===================================================================================================
# 18.12.03 UBR Validation
#===================================================================================================
if ($UBRPre -eq $UBR) {
    Write-Host "===================================================================================================" -ForegroundColor Cyan
    Write-Warning "The Update Build Revision did not change after Windows Updates"
    Write-Warning "There may have been an issue applying the Cumulative Update if this was not expected"
}
if (!($UBR)) {$UBR = $((Get-Date).ToString('mmss'))}

#===================================================================================================
# 18.12.03 Set New Name
#===================================================================================================
            $OSImageName = $($GetWindowsImage.ImageName)
            $OSImageName = $OSImageName -replace "Windows 10", "Win10"
            $OSImageName = $OSImageName -replace "Enterprise", "Ent"
            $OSImageName = $OSImageName -replace "Education", "Edu"
            $OSImageName = $OSImageName -replace "Virtual Desktops", "VD"
            $OSImageName = $OSImageName -replace " for ", " "
            $OSImageName = $OSImageName -replace "Workstations", "Wks"
            $OSImageName = $OSImageName -replace "Windows Server 2016", "Svr2016"
            $OSImageName = $OSImageName -replace "Windows Server 2019", "Svr2019"
            $OSImageName = $OSImageName -replace "ServerStandardACore", "Std Core"
            $OSImageName = $OSImageName -replace "ServerDatacenterACore", "DC Core"
            $OSImageName = $OSImageName -replace "ServerStandardCore", "Std Core"
            $OSImageName = $OSImageName -replace "ServerDatacenterCore", "DC Core"
            $OSImageName = $OSImageName -replace "ServerStandard", "Std"
            $OSImageName = $OSImageName -replace "ServerDatacenter", "DC"
            $OSImageName = $OSImageName -replace "Standard", "Std"
            $OSImageName = $OSImageName -replace "Datacenter", "DC"
            $OSImageName = $OSImageName -replace 'Desktop Experience', 'DTE'
            $OSImageName = $OSImageName -replace '\(', ''
            $OSImageName = $OSImageName -replace '\)', ''

            $OSArchitecture = $($GetWindowsImage.Architecture)
            if ($OSArchitecture -eq 0) {$OSArchitecture = 'x86'}
            elseif ($OSArchitecture -eq 1) {$OSArchitecture = 'MIPS'}
            elseif ($OSArchitecture -eq 2) {$OSArchitecture = 'Alpha'}
            elseif ($OSArchitecture -eq 3) {$OSArchitecture = 'PowerPC'}
            elseif ($OSArchitecture -eq 6) {$OSArchitecture = 'ia64'}
            elseif ($OSArchitecture -eq 9) {$OSArchitecture = 'x64'}

            $OSBuild = $($GetWindowsImage.Build)
            $OSVersionNumber = $null
            if (Test-Path "$LogsXML\CurrentVersion.xml") {
                $RegCurrentVersion = Import-Clixml -Path "$LogsXML\CurrentVersion.xml"
                $OSVersionNumber = $($RegCurrentVersion.ReleaseId)
            } else {
                if ($OSBuild -eq 10240) {$OSVersionNumber = 1507}
                if ($OSBuild -eq 14393) {$OSVersionNumber = 1607}
                if ($OSBuild -eq 15063) {$OSVersionNumber = 1703}
                if ($OSBuild -eq 16299) {$OSVersionNumber = 1709}
                if ($OSBuild -eq 17134) {$OSVersionNumber = 1803}
                if ($OSBuild -eq 17763) {$OSVersionNumber = 1809}
            }

            $OSLanguages = $($GetWindowsImage.Languages)
            if ($null -eq $OSVersionNumber ) {
                Write-Host ""
                Write-Warning "OS Build $OSVersionNumber is not automatically recognized"
                Write-Warning "Check for an updated version of OSBuilder"
                Write-Host ""
                if ($BuildName -like "build*") {$BuildName = "$OSImageName $OSArchitecture"}
            } else {
                if ($BuildName -like "build*") {$BuildName = "$OSImageName $OSArchitecture $OSVersionNumber"}
                
            }
            $BuildName = "$BuildName $OSLanguages"
            if ($($OSLanguages.count) -eq 1) {$BuildName = $BuildName.replace(' en-US', '')}
            
            $NewWorkingPathName = "$BuildName $UBR"
            $NewWorkingPath = "$OSBuilderOSMedia\$NewWorkingPathName"

#===================================================================================================
# 18.12.03 Rename Build Directory
#===================================================================================================
            if (Test-Path $NewWorkingPath) {
                Write-Host ""
                Write-Warning "Trying to rename the Build directory, but it already exists"
                Write-Warning "Appending the mmss to the directory name"
                $NewWorkingPathName = "$NewWorkingPathName $((Get-Date).ToString('mmss'))"
                $NewWorkingPath = "$OSBuilderOSMedia\$NewWorkingPathName"
            }

#===================================================================================================
# 18.12.03 Create Variables
#===================================================================================================
            Get-Variable | Select-Object -Property Name, Value | Export-Clixml "$LogsXML\Variables.xml"
            Get-Variable | Select-Object -Property Name, Value | ConvertTo-Json | Out-File "$LogsJS\Variables.json"

#===================================================================================================
# 18.12.03 Close
#===================================================================================================
            Write-Host "===================================================================================================" -ForegroundColor Cyan
            Write-Host "Closing Phase: Renaming ""$WorkingPath"" to ""$NewWorkingPathName""" -ForegroundColor Cyan
            Stop-Transcript
            Rename-Item -Path "$WorkingPath" -NewName "$NewWorkingPathName" -ErrorAction Stop

#===================================================================================================
# 18.12.03 Create ISO
#===================================================================================================
            if ($CreateISO.IsPresent) {
                Write-Host "===================================================================================================" -ForegroundColor Cyan
                Write-Host "Creating ISO: New-MediaISO -FullName $NewWorkingPath" -ForegroundColor Cyan
                New-MediaISO -FullName "$NewWorkingPath"
            }
        }

#==============================================================================================================
# 18.12.04 Complete
#==============================================================================================================
        Write-Host "===================================================================================================" -ForegroundColor Green
        Write-Host "Complete!" -ForegroundColor Green
        Write-Host "===================================================================================================" -ForegroundColor Green
    }
}