Aktualisieren von Windows-Installationsmedien mit dynamischem Update

In diesem Artikel wird erläutert, wie Sie dynamische Updatepakete vor der Bereitstellung abrufen und auf vorhandene Windows-Images anwenden, und enthält Windows PowerShell Skripts, die Sie zum Automatisieren dieses Prozesses verwenden können.

Volumenlizenzierte Medien sind für jede Version von Windows im Volume Licensing Service Center (VLSC) und anderen relevanten Kanälen wie Windows Update for Business, Windows Server Update Services (WSUS) und Visual Studio-Abonnements verfügbar. Sie können dynamische Updates verwenden, um sicherzustellen, dass Windows-Geräte im Rahmen eines direkten Upgrades über die neuesten Featureupdatepakete verfügen und gleichzeitig language pack und Features on Demand (FODs) beibehalten, die möglicherweise zuvor installiert wurden. Mit dynamischen Updates entfällt außerdem die Notwendigkeit, ein separates Qualitätsupdate im Rahmen des direkten Upgradeprozesses zu installieren.

Dynamisches Update

Immer wenn die Installation eines Featureupdates beginnt (ob über ein Medium oder eine Umgebung, die mit Windows Update verbunden ist), ist dynamisches Update einer der ersten Schritte. Windows Setup kontaktiert einen Microsoft-Endpunkt, um pakete für dynamische Updates abzurufen, und wendet diese Updates dann auf die Installationsmedien Ihres Betriebssystems an. Die Updatepakete enthalten die folgenden Arten von Updates:

  • Updates, um Binärdateien oder andere Dateien zu Setup.exe, die von Setup für Featureupdates verwendet werden
  • Updates für das "sichere Betriebssystem" (SafeOS), das für die Windows-Wiederherstellungsumgebung verwendet wird
  • Updates zum Wartungsstapel, der zum Abschließen des Featureupdates erforderlich ist. Weitere Informationen finden Sie unter Wartungsstapelupdates.
  • Das neueste kumulative Update (Qualitätsupdate)
  • Updates auf anwendbare Treiber, die bereits von Herstellern veröffentlicht wurden, die speziell für dynamische Updates bestimmt sind

Dynamisches Update behält Sprachpakete und Features bei Bedarf bei, indem sie erneut angefordert werden.

Geräte müssen eine Verbindung mit dem Internet herstellen können, um dynamische Updates zu erhalten. In einigen Umgebungen ist es keine Option, dynamische Updates abzurufen. Sie können weiterhin ein medienbasiertes Featureupdate durchführen, indem Sie pakete für dynamische Updates abrufen und auf das Image anwenden, bevor Sie setup auf dem Gerät starten.

Abrufen dynamischer Updatepakete

Sie können dynamische Updatepakete aus dem Microsoft Update-Katalog abrufen. Verwenden Sie an dieser Website die Suchleiste oben rechts, um die Pakete für dynamische Updates für eine bestimmte Version zu finden. Die verschiedenen Pakete für dynamische Updates sind möglicherweise nicht alle in den Ergebnissen einer einzelnen Suche vorhanden, sodass Sie möglicherweise mit verschiedenen Schlüsselwörtern suchen müssen, um alle Updates zu finden. Überprüfen Sie verschiedene Teile der Ergebnisse, um sicherzustellen, dass Sie die erforderlichen Dateien identifiziert haben. In den folgenden Tabellen sind die Schlüsselwerte aufgeführt, die in den Ergebnissen gesucht oder gesucht werden sollen.

Windows 11, Version 22H2 Dynamische Updatepakete

Titel kann jedes dynamische Paket unterscheiden. Bei kumulativen Updates ist der Wartungsstapel eingebettet. Der Wartungsstapel wird nur veröffentlicht, wenn dies für ein bestimmtes kumulatives Update erforderlich ist.

Aktualisieren von Paketen Title
Dynamisches Update des sicheren Betriebssystems Dynamisches YYYY-MM-Sicheres Betriebssystemupdate für Windows 11 Version 22H2
Dynamisches Update einrichten Dynamisches JJJJ-MM-Setupupdate für Windows 11 Version 22H2
Neuestes kumulatives Update Kumulatives JJJJ-MM-Update für Windows 11 Version 22H2
Dynamische Aktualisierung des Wartungsstapels JJJJ-MM Servicing Stack Update für Windows 11 Version 22H2

Windows 11, Version 21H2 Dynamische Updatepakete

Titel, Produkt und Beschreibung sind erforderlich, um jedes dynamische Paket zu unterscheiden. Beim letzten kumulativen Update ist der Wartungsstapel eingebettet. Wartungsstapel wird nur separat veröffentlicht, wenn dies als Voraussetzung für ein bestimmtes kumulatives Update erforderlich ist.

Aktualisieren von Paketen Title Produkt Beschreibung
Dynamisches Update des sicheren Betriebssystems Dynamisches JJJJ-MM-Update für Windows 11 Dynamisches Windows-Betriebssystemupdate ComponentUpdate
Dynamisches Update einrichten Dynamisches JJJJ-MM-Update für Windows 11 dynamisches update Windows 10 und höher SetupUpdate
Neuestes kumulatives Update Kumulatives Update JJJJ-MM für Windows 11
Dynamische Aktualisierung des Wartungsstapels JJJJ-MM Servicing Stack Update für Windows 11 Version 21H2

Dynamische Updatepakete für Windows 10 Version 22H2

Titel, Produkt und Beschreibung sind erforderlich, um jedes dynamische Paket zu unterscheiden. Beim letzten kumulativen Update ist der Wartungsstapel eingebettet. Wartungsstapel wird nur separat veröffentlicht, wenn dies als Voraussetzung für ein bestimmtes kumulatives Update erforderlich ist.

Aktualisieren von Paketen Title Produkt Beschreibung
Dynamisches Update des sicheren Betriebssystems Dynamisches JJJJ-MM-Update für Windows 10 Version 22H2 Dynamisches Windows-Betriebssystemupdate ComponentUpdate
Dynamisches Update einrichten Dynamisches JJJJ-MM-Update für Windows 10 Version 22H2 dynamisches update Windows 10 und höher SetupUpdate
Neuestes kumulatives Update Kumulatives JJJJ-MM-Update für Windows 10 Version 22H2
Dynamische Aktualisierung des Wartungsstapels JJJJ-MM Servicing Stack Update für Windows 10 Version 22H2

Wenn Sie das Image mit zusätzlichen Sprachen oder Features bei Bedarf anpassen möchten, laden Sie zusätzliche Medien-ISO-Dateien aus dem Volume Licensing Service Center herunter. Wenn dynamische Updates beispielsweise für Ihre Geräte deaktiviert werden und Benutzer bestimmte Features bei Bedarf benötigen, können Sie diese im Image vorinstallieren.

Aktualisieren des Windows-Installationsmediums

Das ordnungsgemäße Aktualisieren des Installationsmediums umfasst eine große Anzahl von Aktionen, die auf mehreren verschiedenen Zielen (Imagedateien) ausgeführt werden. Einige Aktionen werden für verschiedene Ziele wiederholt. Die Zielimagedateien umfassen:

  • Windows Preinstallation Environment (WinPE): ein kleines Betriebssystem zum Installieren, Bereitstellen und Reparieren von Windows-Betriebssystemen
  • Windows-Wiederherstellungsumgebung (WinRE): Repariert häufige Ursachen von nicht bootfähigen Betriebssystemen. WinRE basiert auf WinPE und kann mit zusätzlichen Treibern, Sprachen, optionalen Paketen und anderen Tools zur Problembehandlung oder Diagnose angepasst werden.
  • Windows-Betriebssystem: mindestens eine Edition von Windows, die in \sources\install.wim gespeichert ist
  • Windows-Installationsmedien: Die vollständige Sammlung von Dateien und Ordnern auf den Windows-Installationsmedien. Beispiel: \sources-Ordner, \boot-Ordner, Setup.exe usw.

Diese Tabelle zeigt die richtige Reihenfolge zum Anwenden der verschiedenen Aufgaben auf die Dateien. Die vollständige Sequenz beginnt beispielsweise mit dem Hinzufügen des Wartungsstapelupdates zu WinRE (1) und endet mit dem Hinzufügen des Start-Managers von WinPE zu den neuen Medien (28).

Aufgabe WinRE (winre.wim) Betriebssystem (install.wim) WinPE (boot.wim) Neue Medien
Hinzufügen des dynamischen Updates des Wartungsstapels 1 9 17
Hinzufügen eines Sprachpakets 2 10 18
Hinzufügen lokalisierter optionaler Pakete 3 19
Unterstützung für Schriftarten hinzufügen 4 20
Hinzufügen von Text-zu-Sprache 5 21
Lang.ini aktualisieren 22
Hinzufügen von Features bei Bedarf 11
Hinzufügen eines sicheren dynamischen Betriebssystemupdates 6
Hinzufügen des dynamischen Setupupdates 26
Hinzufügen von setup.exe aus WinPE 27
Hinzufügen des Start-Managers aus WinPE 28
Neuestes kumulatives Update hinzufügen 12 23
Bereinigen des Images 7 13 24
Hinzufügen optionaler Komponenten 14
Hinzufügen kumulativer Updates für .NET und .NET 15
Bild exportieren 8 16 25

Hinweis

Ab Februar 2021 werden das neueste kumulative Update- und Wartungsstapelupdate kombiniert und im Microsoft Update-Katalog als neues kombiniertes kumulatives Update verteilt. Für die Schritte 1, 9 und 18, für die das Wartungsstapelupdate zum Aktualisieren der Installationsmedien erforderlich ist, sollten Sie das kombinierte kumulative Update verwenden. Weitere Informationen zum kombinierten kumulativen Update finden Sie unter Wartungsstapelupdates.

Hinweis

Microsoft entfernt die Flash-Komponente von Windows über KB4577586 "Update for Removal of Adobe Flash Player". Sie können Flash auch jederzeit entfernen, indem Sie das Update zwischen den Schritten 20 und 21 in KB4577586 (im Katalog verfügbar) bereitstellen. Ab Juli 2021 wird KB4577586 "Update for Removal of Adobe Flash Player" im neuesten kumulativen Update für Windows 10, Versionen 1607 und 1507, enthalten sein. Das Update wird auch im monatlichen Rollup und im Sicherheitsupdate für Windows 8.1, Windows Server 2012 und Windows Embedded 8 Standard enthalten sein. Weitere Informationen finden Sie unter Update on Adobe Flash Player End of Support( Ende des Supports für Adobe Flash Player).

Mehrere Windows-Editionen

Die Standard Betriebssystemdatei (install.wim) enthält möglicherweise mehrere Editionen von Windows. Es ist möglich, dass nur ein Update für eine bestimmte Edition erforderlich ist, um es basierend auf dem Index bereitzustellen. Oder es kann sein, dass alle Editionen ein Update benötigen. Stellen Sie außerdem sicher, dass Sprachen vor Features bei Bedarf installiert werden und das neueste kumulative Update immer zuletzt angewendet wird.

Zusätzliche Sprachen und Features

Sie müssen dem Image keine weiteren Sprachen und Features hinzufügen, um die Updates durchzuführen, aber es ist eine Möglichkeit, das Image mit mehr Sprachen, optionalen Komponenten und Features bei Bedarf anzupassen, die über das in Ihrem Startimage hinausgehen. Wenn Sie weitere Sprachen und Features hinzufügen, ist es wichtig, diese Änderungen in der richtigen Reihenfolge vorzunehmen: zuerst Wartungsstapelupdates anwenden, dann Spracherneuerungen, dann Featureerneuerungen und schließlich das neueste kumulative Update. Das bereitgestellte Beispielskript installiert eine zweite Sprache (in diesem Fall Japanisch (ja-JP)). Da diese Sprache von einem lp.cab unterstützt wird, ist es nicht erforderlich, ein Language Experience Pack hinzuzufügen. Japanisch wird sowohl dem Standard Betriebssystem als auch der Wiederherstellungsumgebung hinzugefügt, damit der Benutzer die Wiederherstellungsbildschirme auf Japanisch sehen kann. Dies schließt das Hinzufügen lokalisierter Versionen der Pakete ein, die derzeit im Wiederherstellungsimage installiert sind.

Optionale Komponenten können zusammen mit dem .NET-Feature offline installiert werden. Dadurch werden jedoch ausstehende Vorgänge erstellt, die einen Neustart des Geräts erfordern. Daher schlägt der Aufruf zum Ausführen der Imagebereinigung fehl. Es gibt zwei Optionen, um den Bereinigungsfehler zu vermeiden. Eine Möglichkeit besteht darin, den Schritt zur Imagebereinigung zu überspringen, was jedoch zu einer größeren installation.wim führt. Eine weitere Möglichkeit besteht darin, die .NET- und optionalen Komponenten in einem Schritt nach der Bereinigung, aber vor dem Export zu installieren. Dies ist die Option im Beispielskript. Auf diese Weise müssen Sie mit der ursprünglichen Datei install.wim (ohne ausstehende Aktionen) beginnen, wenn Sie das Image beim nächsten Mal (z. B. im nächsten Monat) verwalten oder aktualisieren.

Windows PowerShell Skripts, um dynamische Updates auf ein vorhandenes Image anzuwenden

Diese Beispiele dienen nur zur Veranschaulichung und daher nicht zur Fehlerbehandlung. Das Skript geht davon aus, dass die folgenden Pakete lokal in dieser Ordnerstruktur gespeichert werden:

Ordner Beschreibung
C:\mediaRefresh Übergeordneter Ordner, der das PowerShell-Skript enthält
C:\mediaRefresh\oldMedia Ordner, der die ursprünglichen Medien enthält, die aktualisiert werden. Enthält z. B. Setup.exe und den Ordner \sources.
C:\mediaRefresh\newMedia Ordner, der die aktualisierten Medien enthält. Es wird aus \oldMedia kopiert und dann als Ziel für alle Aktualisierungs- und Bereinigungsvorgänge verwendet.

Erste Schritte

Das Skript deklariert zunächst globale Variablen und erstellt Ordner, die zum Einbinden von Images verwendet werden sollen. Erstellen Sie dann eine Kopie des originalen Mediums von \oldMedia zu \newMedia, wobei sie das originale Medium behalten, falls ein Skriptfehler auftritt und es erforderlich ist, von einem bekannten Zustand aus neu zu beginnen. Außerdem bietet es einen Vergleich zwischen alten und neuen Medien, um Änderungen zu bewerten. Um sicherzustellen, dass die neuen Medien aktualisiert werden, stellen Sie sicher, dass sie nicht schreibgeschützt sind.

#Requires -RunAsAdministrator

function Get-TS { return "{0:HH:mm:ss}" -f [DateTime]::Now }

Write-Output "$(Get-TS): Starting media refresh"

# Declare language for showcasing adding optional localized components
$LANG  = "ja-jp"
$LANG_FONT_CAPABILITY = "jpan"

# Declare media for FOD and LPs
# Note: Starting with Windows 11, version 21H2, the language pack (LANGPACK) ISO has been superseded by the FOD ISO.
# Language packs and the \Windows Preinstallation Environment packages are part of the LOF ISO.
# If you are using this script for Windows 10, modify to mount and use the LANGPACK ISO.
$FOD_ISO_PATH    = "C:\mediaRefresh\packages\FOD-PACKAGES_OEM_PT1_amd64fre_MULTI.iso"

# Declare Dynamic Update packages
$LCU_PATH        = "C:\mediaRefresh\packages\LCU.msu"
$SSU_PATH        = "C:\mediaRefresh\packages\SSU_DU.msu"
$SETUP_DU_PATH   = "C:\mediaRefresh\packages\Setup_DU.cab"
$SAFE_OS_DU_PATH = "C:\mediaRefresh\packages\SafeOS_DU.cab"
$DOTNET_CU_PATH  = "C:\mediaRefresh\packages\DotNet_CU.msu"

# Declare folders for mounted images and temp files
$MEDIA_OLD_PATH  = "C:\mediaRefresh\oldMedia"
$MEDIA_NEW_PATH  = "C:\mediaRefresh\newMedia"
$WORKING_PATH    = "C:\mediaRefresh\temp"
$MAIN_OS_MOUNT   = "C:\mediaRefresh\temp\MainOSMount"
$WINRE_MOUNT     = "C:\mediaRefresh\temp\WinREMount"
$WINPE_MOUNT     = "C:\mediaRefresh\temp\WinPEMount"

# Mount the Features on Demand ISO
Write-Output "$(Get-TS): Mounting FOD ISO"
$FOD_ISO_DRIVE_LETTER = (Mount-DiskImage -ImagePath $FOD_ISO_PATH -ErrorAction stop | Get-Volume).DriveLetter

# Note: Starting with Windows 11, version 21H2, the correct path for main OS language and optional features
# moved to \LanguagesAndOptionalFeatures instead of the root. For Windows 10, use $FOD_PATH = $FOD_ISO_DRIVE_LETTER + ":\"
$FOD_PATH = $FOD_ISO_DRIVE_LETTER + ":\LanguagesAndOptionalFeatures"

# Declare language related cabs
$WINPE_OC_PATH              = "$FOD_ISO_DRIVE_LETTER`:\Windows Preinstallation Environment\x64\WinPE_OCs"
$WINPE_OC_LANG_PATH         = "$WINPE_OC_PATH\$LANG"
$WINPE_OC_LANG_CABS         = Get-ChildItem $WINPE_OC_LANG_PATH -Name
$WINPE_OC_LP_PATH           = "$WINPE_OC_LANG_PATH\lp.cab"
$WINPE_FONT_SUPPORT_PATH    = "$WINPE_OC_PATH\WinPE-FontSupport-$LANG.cab"
$WINPE_SPEECH_TTS_PATH      = "$WINPE_OC_PATH\WinPE-Speech-TTS.cab"
$WINPE_SPEECH_TTS_LANG_PATH = "$WINPE_OC_PATH\WinPE-Speech-TTS-$LANG.cab"
$OS_LP_PATH                 = "$FOD_PATH\Microsoft-Windows-Client-Language-Pack_x64_$LANG.cab"

# Create folders for mounting images and storing temporary files
New-Item -ItemType directory -Path $WORKING_PATH -ErrorAction Stop | Out-Null
New-Item -ItemType directory -Path $MAIN_OS_MOUNT -ErrorAction stop | Out-Null
New-Item -ItemType directory -Path $WINRE_MOUNT -ErrorAction stop | Out-Null
New-Item -ItemType directory -Path $WINPE_MOUNT -ErrorAction stop | Out-Null

# Keep the original media, make a copy of it for the new, updated media.
Write-Output "$(Get-TS): Copying original media to new media path"
Copy-Item -Path $MEDIA_OLD_PATH"\*" -Destination $MEDIA_NEW_PATH -Force -Recurse -ErrorAction stop | Out-Null
Get-ChildItem -Path $MEDIA_NEW_PATH -Recurse | Where-Object { -not $_.PSIsContainer -and $_.IsReadOnly } | ForEach-Object { $_.IsReadOnly = $false }

Aktualisieren von WinRE und jeder Standard Windows-Edition des Betriebssystems

Das Skript aktualisiert jede Edition von Windows in der Standard Betriebssystemdatei (install.wim). Für jede Edition wird das Standard Betriebssystemimage eingebunden.

Für das erste Image wird Winre.wim in den Arbeitsordner kopiert und eingebunden. Anschließend wird das dynamische Update des Wartungsstapels angewendet, da seine Komponenten zum Aktualisieren anderer Komponenten verwendet werden. Da das Skript optional Japanisch hinzufügt, fügt es dem Image das Sprachpaket hinzu und installiert die japanischen Versionen aller optionalen Pakete, die bereits in Winre.wim installiert sind. Anschließend wird das Dynamische Updatepaket für sicheres Betriebssystem angewendet. Es wird durch Bereinigen und Exportieren des Bilds abgeschlossen, um die Bildgröße zu reduzieren.

Als Nächstes wendet das Skript für das eingebundene Betriebssystemimage das dynamische Update des Wartungsstapels an. Anschließend werden die Japanischen Sprachunterstützung und dann die Japanischen Sprachfeatures hinzugefügt. Im Gegensatz zu den Paketen für dynamische Updates wird verwendet Add-WindowsCapability , um diese Features hinzuzufügen. Eine vollständige Liste dieser Features und den zugehörigen Funktionsnamen finden Sie unter Verfügbare Features bei Bedarf. Jetzt ist es an der Zeit, andere optionale Komponenten zu aktivieren oder andere Features bei Bedarf hinzuzufügen. Wenn ein solches Feature über ein kumulatives Update verfügt (z. B. .NET), ist dies der Zeitpunkt, um diese anzuwenden. Das Skript fährt dann mit der Anwendung des neuesten kumulativen Updates fort. Schließlich bereinigt und exportiert das Skript das Image. Sie können optionale Komponenten zusammen mit dem .NET-Feature offline installieren, aber dafür muss das Gerät neu gestartet werden. Aus diesem Grund installiert das Skript .NET und optionale Komponenten nach der Bereinigung und vor dem Export.

Dieser Vorgang wird für jede Edition von Windows innerhalb der Standard Betriebssystemdatei wiederholt. Um die Größe zu reduzieren, wird die gewartete Winre.wim-Datei aus dem ersten Image gespeichert und verwendet, um jede nachfolgende Windows-Edition zu aktualisieren. Dadurch wird die endgültige Größe von install.wim reduziert.

#
# Update each main OS Windows image including the Windows Recovery Environment (WinRE)
#

# Get the list of images contained within WinPE
$WINOS_IMAGES = Get-WindowsImage -ImagePath $MEDIA_NEW_PATH"\sources\install.wim"

Foreach ($IMAGE in $WINOS_IMAGES) {

    # first mount the main OS image
    Write-Output "$(Get-TS): Mounting main OS, image index $($IMAGE.ImageIndex)"
    Mount-WindowsImage -ImagePath $MEDIA_NEW_PATH"\sources\install.wim" -Index $IMAGE.ImageIndex -Path $MAIN_OS_MOUNT -ErrorAction stop| Out-Null    

    if ($IMAGE.ImageIndex -eq "1") {

        #
        # update Windows Recovery Environment (WinRE) within this OS image
        #
        Copy-Item -Path $MAIN_OS_MOUNT"\windows\system32\recovery\winre.wim" -Destination $WORKING_PATH"\winre.wim" -Force -ErrorAction stop | Out-Null
        Write-Output "$(Get-TS): Mounting WinRE"
        Mount-WindowsImage -ImagePath $WORKING_PATH"\winre.wim" -Index 1 -Path $WINRE_MOUNT -ErrorAction stop | Out-Null

        # Add servicing stack update (Step 1 from the table)

        # Depending on the Windows release that you are updating, there are 2 different approaches for updating the servicing stack
        # The first approach is to use the combined cumulative update. This is for Windows releases that are shipping a combined 
        # cumulative update that includes the servicing stack updates (i.e. SSU + LCU are combined). Windows 11, version 21H2 and 
        # Windows 11, version 22H2 are examples. In these cases, the servicing stack update is not published seperately; the combined 
        # cumulative update should be used for this step. However, in hopefully rare cases, there may breaking change in the combined 
        # cumulative update format, that requires a standalone servicing stack update to be published, and installed first before the 
        # combined cumulative update can be installed. 

        # This is the code to handle the rare case that the SSU is published and required for the combined cumulative update
        # Write-Output "$(Get-TS): Adding package $SSU_PATH"
        # Add-WindowsPackage -Path $WINRE_MOUNT -PackagePath $SSU_PATH | Out-Null  

        # Now, attempt the combined cumulative update.
        # There is a known issue where the servicing stack update is installed, but the cumulative update will fail. This error should 
        # be caught and ignored, as the last step will be to apply the Safe OS update and thus the image will be left with the correct 
        # packages installed.

        try
        {
            Add-WindowsPackage -Path $WINRE_MOUNT -PackagePath $LCU_PATH | Out-Null  
        }
        Catch
        {
            $theError = $_
            Write-Output "$(Get-TS): $theError"
    
            if ($theError.Exception -like "*0x8007007e*") {
                Write-Output "$(Get-TS): This failure is a known issue with combined cumulative update, we can ignore."
            }
            else {
                throw
            }
        }

        # The second approach for Step 1 is for Windows releases that have not adopted the combined cumulative update
        # but instead continue to have a seperate servicing stack update published. In this case, we'll install the SSU
        # update. This second approach is commented out below.

        # Write-Output "$(Get-TS): Adding package $SSU_PATH"
        # Add-WindowsPackage -Path $WINRE_MOUNT -PackagePath $SSU_PATH | Out-Null  

        #
        # Optional: Add the language to recovery environment
        #
        # Install lp.cab cab
        Write-Output "$(Get-TS): Adding package $WINPE_OC_LP_PATH"
        Add-WindowsPackage -Path $WINRE_MOUNT -PackagePath $WINPE_OC_LP_PATH -ErrorAction stop | Out-Null  

        # Install language cabs for each optional package installed
        $WINRE_INSTALLED_OC = Get-WindowsPackage -Path $WINRE_MOUNT
        Foreach ($PACKAGE in $WINRE_INSTALLED_OC) {

            if ( ($PACKAGE.PackageState -eq "Installed") `
                    -and ($PACKAGE.PackageName.startsWith("WinPE-")) `
                    -and ($PACKAGE.ReleaseType -eq "FeaturePack") ) {

                $INDEX = $PACKAGE.PackageName.IndexOf("-Package")
                if ($INDEX -ge 0) {
                    $OC_CAB = $PACKAGE.PackageName.Substring(0, $INDEX) + "_" + $LANG + ".cab"
                    if ($WINPE_OC_LANG_CABS.Contains($OC_CAB)) {
                        $OC_CAB_PATH = Join-Path $WINPE_OC_LANG_PATH $OC_CAB
                        Write-Output "$(Get-TS): Adding package $OC_CAB_PATH"
                        Add-WindowsPackage -Path $WINRE_MOUNT -PackagePath $OC_CAB_PATH -ErrorAction stop | Out-Null  
                    }
                }
            }
        }

        # Add font support for the new language
        if ( (Test-Path -Path $WINPE_FONT_SUPPORT_PATH) ) {
            Write-Output "$(Get-TS): Adding package $WINPE_FONT_SUPPORT_PATH"
            Add-WindowsPackage -Path $WINRE_MOUNT -PackagePath $WINPE_FONT_SUPPORT_PATH -ErrorAction stop | Out-Null
        }

        # Add TTS support for the new language
        if (Test-Path -Path $WINPE_SPEECH_TTS_PATH) {
            if ( (Test-Path -Path $WINPE_SPEECH_TTS_LANG_PATH) ) {

                Write-Output "$(Get-TS): Adding package $WINPE_SPEECH_TTS_PATH"
                Add-WindowsPackage -Path $WINRE_MOUNT -PackagePath $WINPE_SPEECH_TTS_PATH -ErrorAction stop | Out-Null

                Write-Output "$(Get-TS): Adding package $WINPE_SPEECH_TTS_LANG_PATH"
                Add-WindowsPackage -Path $WINRE_MOUNT -PackagePath $WINPE_SPEECH_TTS_LANG_PATH -ErrorAction stop | Out-Null
            }
        }

        # Add Safe OS
        Write-Output "$(Get-TS): Adding package $SAFE_OS_DU_PATH"
        Add-WindowsPackage -Path $WINRE_MOUNT -PackagePath $SAFE_OS_DU_PATH -ErrorAction stop | Out-Null

        # Perform image cleanup
        Write-Output "$(Get-TS): Performing image cleanup on WinRE"
        DISM /image:$WINRE_MOUNT /cleanup-image /StartComponentCleanup /ResetBase /Defer | Out-Null

        # Dismount
        Dismount-WindowsImage -Path $WINRE_MOUNT  -Save -ErrorAction stop | Out-Null

        # Export
        Write-Output "$(Get-TS): Exporting image to $WORKING_PATH\winre.wim"
        Export-WindowsImage -SourceImagePath $WORKING_PATH"\winre.wim" -SourceIndex 1 -DestinationImagePath $WORKING_PATH"\winre2.wim" -ErrorAction stop | Out-Null

    }
    
    Copy-Item -Path $WORKING_PATH"\winre2.wim" -Destination $MAIN_OS_MOUNT"\windows\system32\recovery\winre.wim" -Force -ErrorAction stop | Out-Null
    
    #
    # update Main OS
    #

    # Add servicing stack update (Step 18 from the table)

    # Depending on the Windows release that you are updating, there are 2 different approaches for updating the servicing stack
    # The first approach is to use the combined cumulative update. This is for Windows releases that are shipping a combined cumulative update that
    # includes the servicing stack updates (i.e. SSU + LCU are combined). Windows 11, version 21H2 and Windows 11, version 22H2 are examples. In these
    # cases, the servicing stack update is not published seperately; the combined cumulative update should be used for this step. However, in hopefully
    # rare cases, there may breaking change in the combined cumulative update format, that requires a standalone servicing stack update to be published, 
    # and installed first before the combined cumulative update can be installed. 

    # This is the code to handle the rare case that the SSU is published and required for the combined cumulative update
    # Write-Output "$(Get-TS): Adding package $SSU_PATH"
    # Add-WindowsPackage -Path $MAIN_OS_MOUNT -PackagePath $SSU_PATH | Out-Null  

    # Now, attempt the combined cumulative update. Unlike WinRE and WinPE, we don't need to check for error 0x8007007e
    Write-Output "$(Get-TS): Adding package $LCU_PATH"
    Add-WindowsPackage -Path $MAIN_OS_MOUNT -PackagePath $LCU_PATH | Out-Null  

    # The second approach for Step 18 is for Windows releases that have not adopted the combined cumulative update
    # but instead continue to have a seperate servicing stack update published. In this case, we'll install the SSU
    # update. This second approach is commented out below.

    # Write-Output "$(Get-TS): Adding package $SSU_PATH"
    # Add-WindowsPackage -Path $MAIN_OS_MOUNT -PackagePath $SSU_PATH | Out-Null  

    # Optional: Add language to main OS
    Write-Output "$(Get-TS): Adding package $OS_LP_PATH"
    Add-WindowsPackage -Path $MAIN_OS_MOUNT -PackagePath $OS_LP_PATH -ErrorAction stop | Out-Null  

    # Optional: Add a Features on Demand to the image
    Write-Output "$(Get-TS): Adding language FOD: Language.Fonts.Jpan~~~und-JPAN~0.0.1.0"
    Add-WindowsCapability -Name "Language.Fonts.$LANG_FONT_CAPABILITY~~~und-$LANG_FONT_CAPABILITY~0.0.1.0" -Path $MAIN_OS_MOUNT -Source $FOD_PATH -ErrorAction stop | Out-Null

    Write-Output "$(Get-TS): Adding language FOD: Language.Basic~~~$LANG~0.0.1.0"
    Add-WindowsCapability -Name "Language.Basic~~~$LANG~0.0.1.0" -Path $MAIN_OS_MOUNT -Source $FOD_PATH -ErrorAction stop | Out-Null

    Write-Output "$(Get-TS): Adding language FOD: Language.OCR~~~$LANG~0.0.1.0"
    Add-WindowsCapability -Name "Language.OCR~~~$LANG~0.0.1.0" -Path $MAIN_OS_MOUNT -Source $FOD_PATH -ErrorAction stop | Out-Null

    Write-Output "$(Get-TS): Adding language FOD: Language.Handwriting~~~$LANG~0.0.1.0"
    Add-WindowsCapability -Name "Language.Handwriting~~~$LANG~0.0.1.0" -Path $MAIN_OS_MOUNT -Source $FOD_PATH -ErrorAction stop | Out-Null

    Write-Output "$(Get-TS): Adding language FOD: Language.TextToSpeech~~~$LANG~0.0.1.0"
    Add-WindowsCapability -Name "Language.TextToSpeech~~~$LANG~0.0.1.0" -Path $MAIN_OS_MOUNT -Source $FOD_PATH -ErrorAction stop | Out-Null

    Write-Output "$(Get-TS): Adding language FOD:Language.Speech~~~$LANG~0.0.1.0"
    Add-WindowsCapability -Name "Language.Speech~~~$LANG~0.0.1.0" -Path $MAIN_OS_MOUNT -Source $FOD_PATH -ErrorAction stop | Out-Null

    # Note: If I wanted to enable additional Features on Demand, I'd add these here.

    # Add latest cumulative update
    Write-Output "$(Get-TS): Adding package $LCU_PATH"
    Add-WindowsPackage -Path $MAIN_OS_MOUNT -PackagePath $LCU_PATH -ErrorAction stop | Out-Null

    # Perform image cleanup
    Write-Output "$(Get-TS): Performing image cleanup on main OS"
    DISM /image:$MAIN_OS_MOUNT /cleanup-image /StartComponentCleanup | Out-Null

    #
    # Note: If I wanted to enable additional Optional Components, I'd add these here.
    # In addition, we'll add .NET 3.5 here as well. Both .NET and Optional Components might require
    # the image to be booted, and thus if we tried to cleanup after installation, it would fail.
    #

    Write-Output "$(Get-TS): Adding NetFX3~~~~"
    Add-WindowsCapability -Name "NetFX3~~~~" -Path $MAIN_OS_MOUNT -Source $FOD_PATH -ErrorAction stop | Out-Null

    # Add .NET Cumulative Update
    Write-Output "$(Get-TS): Adding package $DOTNET_CU_PATH"
    Add-WindowsPackage -Path $MAIN_OS_MOUNT -PackagePath $DOTNET_CU_PATH -ErrorAction stop | Out-Null

    # Dismount
    Dismount-WindowsImage -Path $MAIN_OS_MOUNT -Save -ErrorAction stop | Out-Null

    # Export
    Write-Output "$(Get-TS): Exporting image to $WORKING_PATH\install2.wim"
    Export-WindowsImage -SourceImagePath $MEDIA_NEW_PATH"\sources\install.wim" -SourceIndex $IMAGE.ImageIndex -DestinationImagePath $WORKING_PATH"\install2.wim" -ErrorAction stop | Out-Null

}

Move-Item -Path $WORKING_PATH"\install2.wim" -Destination $MEDIA_NEW_PATH"\sources\install.wim" -Force -ErrorAction stop | Out-Null

WinPE aktualisieren

Dieses Skript ähnelt dem Skript, das WinRE aktualisiert, aber stattdessen wird Boot.wim eingebunden, die Pakete mit dem letzten kumulativen Update zuletzt angewendet und gespeichert. Dies wird für alle Images innerhalb von Boot.wim wiederholt, in der Regel zwei Images. Zunächst wird das dynamische Update des Wartungsstapels angewendet. Da das Skript dieses Medium mit Japanisch an passt, installiert es das Sprachpaket aus dem WinPE-Ordner in der Sprachpaket-ISO. Darüber hinaus werden Schriftunterstützung und Text-zu-Sprache-Unterstützung (Text-to-Speech, TTS) hinzugefügt. Da das Skript eine neue Sprache hinzufügt, wird lang.ini neu erstellt, mit dem im Image installierte Sprachen identifiziert werden. Für das zweite Image speichern wir setup.exe zur späteren Verwendung, um sicherzustellen, dass diese Version mit der \sources\setup.exe Version des Installationsmediums übereinstimmt. Wenn diese Binärdateien nicht identisch sind, schlägt Windows Setup während der Installation fehl. Wir speichern auch die Serviced Boot Manager-Dateien zur späteren Verwendung im Skript. Schließlich bereinigt und exportiert das Skript Boot.wim und kopiert sie wieder auf die neuen Medien.

#
# update Windows Preinstallation Environment (WinPE)
#

# Get the list of images contained within WinPE
$WINPE_IMAGES = Get-WindowsImage -ImagePath $MEDIA_NEW_PATH"\sources\boot.wim"

Foreach ($IMAGE in $WINPE_IMAGES) {

    # update WinPE
    Write-Output "$(Get-TS): Mounting WinPE, image index $($IMAGE.ImageIndex)"
    Mount-WindowsImage -ImagePath $MEDIA_NEW_PATH"\sources\boot.wim" -Index $IMAGE.ImageIndex -Path $WINPE_MOUNT -ErrorAction stop | Out-Null  

    # Add servicing stack update (Step 9 from the table)

    # Depending on the Windows release that you are updating, there are 2 different approaches for updating the servicing stack
    # The first approach is to use the combined cumulative update. This is for Windows releases that are shipping a combined 
    # cumulative update that includes the servicing stack updates (i.e. SSU + LCU are combined). Windows 11, version 21H2 and 
    # Windows 11, version 22H2 are examples. In these cases, the servicing stack update is not published separately; the combined 
    # cumulative update should be used for this step. However, in hopefully rare cases, there may breaking change in the combined 
    # cumulative update format, that requires a standalone servicing stack update to be published, and installed first before the 
    # combined cumulative update can be installed. 

    # This is the code to handle the rare case that the SSU is published and required for the combined cumulative update
    # Write-Output "$(Get-TS): Adding package $SSU_PATH"
    # Add-WindowsPackage -Path $WINPE_MOUNT -PackagePath $SSU_PATH | Out-Null  

    # Now, attempt the combined cumulative update.
    # There is a known issue where the servicing stack update is installed, but the cumulative update will fail.
    # This error should be caught and ignored, as the last step will be to apply the cumulative update 
    # (or in this case the combined cumulative update) and thus the image will be left with the correct packages installed.

    try
    {
        Add-WindowsPackage -Path $WINPE_MOUNT -PackagePath $LCU_PATH | Out-Null  
    }
    Catch
    {
        $theError = $_
        Write-Output "$(Get-TS): $theError"

        if ($theError.Exception -like "*0x8007007e*") {
            Write-Output "$(Get-TS): This failure is a known issue with combined cumulative update, we can ignore."
        }
        else {
            throw
        }
    }

    # The second approach for Step 9 is for Windows releases that have not adopted the combined cumulative update
    # but instead continue to have a separate servicing stack update published. In this case, we'll install the SSU
    # update. This second approach is commented out below.

    # Write-Output "$(Get-TS): Adding package $SSU_PATH"
    # Add-WindowsPackage -Path $WINPE_MOUNT -PackagePath $SSU_PATH | Out-Null 

    # Install lp.cab cab
    Write-Output "$(Get-TS): Adding package $WINPE_OC_LP_PATH"
    Add-WindowsPackage -Path $WINPE_MOUNT -PackagePath $WINPE_OC_LP_PATH -ErrorAction stop | Out-Null  

    # Install language cabs for each optional package installed
    $WINPE_INSTALLED_OC = Get-WindowsPackage -Path $WINPE_MOUNT
    Foreach ($PACKAGE in $WINPE_INSTALLED_OC) {

        if ( ($PACKAGE.PackageState -eq "Installed") `
                -and ($PACKAGE.PackageName.startsWith("WinPE-")) `
                -and ($PACKAGE.ReleaseType -eq "FeaturePack") ) {

            $INDEX = $PACKAGE.PackageName.IndexOf("-Package")
            if ($INDEX -ge 0) {

                $OC_CAB = $PACKAGE.PackageName.Substring(0, $INDEX) + "_" + $LANG + ".cab"
                if ($WINPE_OC_LANG_CABS.Contains($OC_CAB)) {
                    $OC_CAB_PATH = Join-Path $WINPE_OC_LANG_PATH $OC_CAB
                    Write-Output "$(Get-TS): Adding package $OC_CAB_PATH"
                    Add-WindowsPackage -Path $WINPE_MOUNT -PackagePath $OC_CAB_PATH -ErrorAction stop | Out-Null  
                }
            }
        }
    }

    # Add font support for the new language
    if ( (Test-Path -Path $WINPE_FONT_SUPPORT_PATH) ) {
        Write-Output "$(Get-TS): Adding package $WINPE_FONT_SUPPORT_PATH"
        Add-WindowsPackage -Path $WINPE_MOUNT -PackagePath $WINPE_FONT_SUPPORT_PATH -ErrorAction stop | Out-Null
    }

    # Add TTS support for the new language
    if (Test-Path -Path $WINPE_SPEECH_TTS_PATH) {
        if ( (Test-Path -Path $WINPE_SPEECH_TTS_LANG_PATH) ) {

            Write-Output "$(Get-TS): Adding package $WINPE_SPEECH_TTS_PATH"
            Add-WindowsPackage -Path $WINPE_MOUNT -PackagePath $WINPE_SPEECH_TTS_PATH -ErrorAction stop | Out-Null

            Write-Output "$(Get-TS): Adding package $WINPE_SPEECH_TTS_LANG_PATH"
            Add-WindowsPackage -Path $WINPE_MOUNT -PackagePath $WINPE_SPEECH_TTS_LANG_PATH -ErrorAction stop | Out-Null
        }
    }

    # Generates a new Lang.ini file which is used to define the language packs inside the image
    if ( (Test-Path -Path $WINPE_MOUNT"\sources\lang.ini") ) {
        Write-Output "$(Get-TS): Updating lang.ini"
        DISM /image:$WINPE_MOUNT /Gen-LangINI /distribution:$WINPE_MOUNT | Out-Null
    }

    # Add latest cumulative update
    Write-Output "$(Get-TS): Adding package $LCU_PATH"
    Add-WindowsPackage -Path $WINPE_MOUNT -PackagePath $LCU_PATH -ErrorAction stop | Out-Null  

    # Perform image cleanup
    Write-Output "$(Get-TS): Performing image cleanup on WinPE"
    DISM /image:$WINPE_MOUNT /cleanup-image /StartComponentCleanup /ResetBase /Defer | Out-Null

    if ($IMAGE.ImageIndex -eq "2") {

        # Save setup.exe for later use. This will address possible binary mismatch with the version in the main OS \sources folder
        Copy-Item -Path $WINPE_MOUNT"\sources\setup.exe" -Destination $WORKING_PATH"\setup.exe" -Force -ErrorAction stop | Out-Null
        
        # Save serviced boot manager files later copy to the root media.
        Copy-Item -Path $WINPE_MOUNT"\Windows\boot\efi\bootmgfw.efi" -Destination $WORKING_PATH"\bootmgfw.efi" -Force -ErrorAction stop | Out-Null
        Copy-Item -Path $WINPE_MOUNT"\Windows\boot\efi\bootmgr.efi" -Destination $WORKING_PATH"\bootmgr.efi" -Force -ErrorAction stop | Out-Null
    
    }
        
    # Dismount
    Dismount-WindowsImage -Path $WINPE_MOUNT -Save -ErrorAction stop | Out-Null

    #Export WinPE
    Write-Output "$(Get-TS): Exporting image to $WORKING_PATH\boot2.wim"
    Export-WindowsImage -SourceImagePath $MEDIA_NEW_PATH"\sources\boot.wim" -SourceIndex $IMAGE.ImageIndex -DestinationImagePath $WORKING_PATH"\boot2.wim" -ErrorAction stop | Out-Null

}

Move-Item -Path $WORKING_PATH"\boot2.wim" -Destination $MEDIA_NEW_PATH"\sources\boot.wim" -Force -ErrorAction stop | Out-Null

Aktualisieren der verbleibenden Mediendateien

Dieser Teil des Skripts aktualisiert die Setupdateien. Es kopiert einfach die einzelnen Dateien im Paket "Dynamisches Update einrichten" auf die neuen Medien. In diesem Schritt werden nach Bedarf aktualisierte Setupdateien zusammen mit der neuesten Kompatibilitätsdatenbank und Ersatzkomponentenmanifesten hinzugefügt. Dieses Skript ersetzt außerdem setup.exe- und Start-Manager-Dateien mithilfe der zuvor von WinPE gespeicherten Versionen.

#
# update remaining files on media
#

# Add Setup DU by copy the files from the package into the newMedia
Write-Output "$(Get-TS): Adding package $SETUP_DU_PATH"
cmd.exe /c $env:SystemRoot\System32\expand.exe $SETUP_DU_PATH -F:* $MEDIA_NEW_PATH"\sources" | Out-Null

# Copy setup.exe from boot.wim, saved earlier.
Write-Output "$(Get-TS): Copying $WORKING_PATH\setup.exe to $MEDIA_NEW_PATH\sources\setup.exe"
Copy-Item -Path $WORKING_PATH"\setup.exe" -Destination $MEDIA_NEW_PATH"\sources\setup.exe" -Force -ErrorAction stop | Out-Null


# Copy bootmgr files from boot.wim, saved earlier.
$MEDIA_NEW_FILES = Get-ChildItem $MEDIA_NEW_PATH -Force -Recurse -Filter b*.efi

Foreach ($File in $MEDIA_NEW_FILES){
    if (($File.Name -ieq "bootmgfw.efi") -or `
        ($File.Name -ieq "bootx64.efi") -or `
        ($File.Name -ieq "bootia32.efi") -or `
        ($File.Name -ieq "bootaa64.efi")) 
    {
        Write-Output "$(Get-TS): Copying $WORKING_PATH\bootmgfw.efi to $($File.FullName)"
        Copy-Item -Path $WORKING_PATH"\bootmgfw.efi" -Destination $File.FullName -Force -ErrorAction stop | Out-Null
    }
    elseif ($File.Name -ieq "bootmgr.efi") 
    {
        Write-Output "$(Get-TS): Copying $WORKING_PATH\bootmgr.efi to $($File.FullName)"
        Copy-Item -Path $WORKING_PATH"\bootmgr.efi" -Destination $File.FullName -Force -ErrorAction stop | Out-Null
    }
}

Fertigstellung

Als letzten Schritt entfernt das Skript den Arbeitsordner temporärer Dateien und hebt die Einbindung unseres Sprachpakets und der Features bei Bedarf isOs auf.

#
# Perform final cleanup
#

# Remove our working folder
Remove-Item -Path $WORKING_PATH -Recurse -Force -ErrorAction stop | Out-Null

# Dismount ISO images
Write-Output "$(Get-TS): Dismounting ISO images"
Dismount-DiskImage -ImagePath $FOD_ISO_PATH -ErrorAction stop | Out-Null

Write-Output "$(Get-TS): Media refresh completed!"