Freigeben über


Migrieren und Abrufen optionaler Windows-Inhalte während Updates

Dieser Artikel enthält einige Hintergrundinformationen zum Problem der Beibehaltung von Sprachressourcen und Features bei Bedarf während Betriebssystemupdates und bietet Anleitungen, die Ihnen helfen, kurzfristig voranzukommen und sich langfristig vorzubereiten.

Wenn Sie das Betriebssystem aktualisieren, ist es wichtig, Sprachressourcen und Features on Demand (FODs) beizubehalten. Viele kommerzielle Organisationen verwenden Configuration Manager oder andere Verwaltungstools, um das Windows-Clientsetup mithilfe eines lokalen Windows-Images oder einer WIM-Datei (ein medienbasiertes oder tasksequenzbasiertes Update) zu verteilen und zu orchestrieren. Andere führen direkte Updates mithilfe eines genehmigten Windows-Clientfeatureupdates durch, indem sie Windows Server Update Services (WSUS), Configuration Manager oder gleichwertige Tools (ein wartungsbasiertes Update) verwenden.

Keiner der Beiden Ansätze enthält den vollständigen Satz optionaler Windows-Features, die das Gerät eines Benutzers möglicherweise benötigt, sodass diese Features nicht zum neuen Betriebssystem migriert werden. In der Vergangenheit waren diese Features weder in Configuration Manager noch in WSUS für den lokalen Erwerb nach einem Featureupdate verfügbar.

Was ist optionaler Inhalt?

Optionale Inhalte umfassen die folgenden Elemente:

  • Allgemeine Features bei Bedarf auch als FODs bezeichnet (z. B. Windows Mixed Reality)
  • Sprachbasierte und regionale FODs (z. B. Language.Basic~~~ja-jp~0.0.1.0)
  • Lokale Erfahrungspakete
  • Sprachpakete

Optionale Inhalte sind standardmäßig nicht in der Windows-Imagedatei enthalten, die Teil der Betriebssystemmedien ist, die im Volume Licensing Service Center (VLSC) verfügbar sind. Stattdessen wird es als zusätzliche ISO-Datei auf VLSC veröffentlicht. Das Senden dieser Features aus den Betriebssystemmedien und der separate Versand dieser Features reduziert den Speicherplatzbedarf von Windows. Dieser Ansatz bietet mehr Platz für die Daten des Benutzers. Außerdem wird der Zeitaufwand für die Bedienung des Betriebssystems reduziert, unabhängig davon, ob ein monatliches Qualitätsupdate installiert oder auf eine neuere Version aktualisiert wird. Ein kleineres Windows-Standardimage bedeutet auch, dass weniger Daten über das Netzwerk übertragen werden.

Warum ist das Abrufen von optionalen Inhalten eine Herausforderung?

Die Herausforderungen im Zusammenhang mit optionalen Inhalten lassen sich in der Regel in zwei Gruppen einteilen:

Unvollständige Betriebssystemupdates

Die erste Herausforderung bezieht sich auf die Inhaltsmigration während eines Featureupdates. Wenn Windows Setup ein direktes Update durchführt, wird das neue Betriebssystem auf den Datenträger des Benutzers zusammen mit der alten Version in einem temporären Ordner geschrieben, in dem ein zweites sauber Betriebssystem installiert und für den Wechsel des Benutzers vorbereitet wird. Wenn der Vorgang ausgeführt wird, listet Windows Setup optionale Inhalte auf, die bereits in der aktuellen Version installiert sind, und plant, die neue Version dieses Inhalts im neuen Betriebssystem zu installieren.

Windows Setup benötigt Zugriff auf den optionalen Inhalt. Da optionale Inhalte nicht standardmäßig im Windows-Image enthalten sind, muss Windows Setup an anderer Stelle suchen, um die Windows-Pakete abzurufen, sie zu stagingen und sie dann im neuen Betriebssystem zu installieren. Wenn der Inhalt nicht gefunden werden kann, ist das Ergebnis ein Update, bei dem Features auf dem Gerät fehlen, ein frustrierter Endbenutzer und wahrscheinlich ein Helpdesk-Anruf. Dieser Problempunkt wird manchmal als Fehler beim Migrieren optionaler Inhalte während des Updates bezeichnet. Bei medienbasierten Updates versucht Windows automatisch erneut, sobald das neue Betriebssystem gestartet wird. Wir nennen dies latente Akquisition.

Fehler bei der vom Benutzer initiierten Featureerfassung

Die zweite Herausforderung umfasst einen Fehler beim Abrufen von Features, wenn ein Benutzer sie anfordert. Stellen Sie sich vor, ein Benutzer führt ein Gerät mit einer neuen Version des Windows-Clients aus, entweder mithilfe einer sauber-Installation oder eines direkten Updates. Der Benutzer besucht die Einstellungen und versucht, eine zweite Sprache, weitere Sprachfunktionen oder andere optionale Inhalte zu installieren. Da diese Features nicht im Betriebssystem enthalten sind, müssen die Pakete abgerufen werden. Für einen typischen Benutzer mit Internetzugriff erhält Windows die Features aus einem nahe gelegenen Microsoft Content Delivery Network, und alles funktioniert wie vorgesehen. Für kommerzielle Benutzer haben einige möglicherweise keinen Internetzugriff oder verfügen über Richtlinien, um den Erwerb über das Internet zu verhindern. In diesen Situationen muss Windows den Inhalt von einem alternativen Speicherort abrufen. Wenn der Inhalt nicht gefunden werden kann, sind Die Benutzer frustriert, und es kann zu einem weiteren Helpdesk-Anruf kommen. Dieser Problempunkt wird manchmal als Fehler beim Abrufen optionaler Inhalte bezeichnet.

Optionen zum Abrufen optionaler Inhalte

Die meisten kommerziellen Organisationen verstehen die oben beschriebenen Probleme, und Diskussionen beginnen in der Regel damit, dass sie fragen, welche Pläne zur Bewältigung dieser Herausforderungen verfügbar sind. Die folgende Tabelle enthält mehrere Optionen, die in Betracht gezogen werden müssen, je nachdem, wie Sie den Windows-Client derzeit bereitstellen. Die folgenden Definitionen werden in den Tabellenüberschriften verwendet:

  • Migration: Unterstützt die optionale Inhaltsmigration während eines Updates.
  • Erwerb: Unterstützt die optionale Inhaltserfassung (d. a. vom Benutzer initiiert).
  • Medien: Gilt für medienbasierte Bereitstellungen.
  • Wartung: Gilt für wartungsbasierte Bereitstellungen.
Methode Migration Acquisition Medien Wartung
Option 1: Verwenden von Windows Update Ja Ja Nein Ja
Option 2: Verwenden von WSUS mit UUP-Integration Ja Ja Nein Ja
Option 3: Dynamisches Update aktivieren Ja Nein Ja Ja
Option 4: Anpassen des Windows-Images vor der Bereitstellung Ja Nein Ja Nein
Option 5: Installieren von Sprachfeatures während der Bereitstellung Teilweise Nein Ja Nein
Option 6: Installieren optionaler Inhalte nach der Bereitstellung Ja Nein Ja Ja
Option 7: Konfigurieren einer alternativen Quelle für Features bei Bedarf Nein Teilweise Ja Ja

Option 1: Verwenden von Windows Update

Windows Update Clientrichtlinien lösen das optionale Inhaltsproblem. Optionale Inhalte werden veröffentlicht und können von Windows Setup aus einem nahe gelegenen Microsoft Content Delivery Network abgerufen und mithilfe der Unified Update Platform abgerufen werden. Optionale Inhaltsmigrations- und -erfassungsszenarien funktionieren nur, wenn das Gerät mit einem Updatedienst verbunden ist, der die Einheitliche Updateplattform verwendet, z. B. Windows Update oder Windows Update Clientrichtlinien. Wenn ein Sprachpaket während des Updates aus irgendeinem Grund nicht installiert werden kann, wird für das Update automatisch ein Rollback ausgeführt.

Die Unified Update Platform ist eine Verbesserung der zugrunde liegenden Windows Update-Technologie, die zu kleineren Downloadgrößen und einem effizienteren Protokoll für die Suche nach Updates, das Abrufen und Installieren der benötigten Pakete und die Aktualisierung in einem Updateschritt führt. Die Technologie ist vereinheitlicht, da sie den Updatestapel für Windows-Clients, Windows Server und andere Produkte wie HoloLens zusammenführt.

Erwägen Sie, zu Windows Update Clientrichtlinien zu wechseln. Das optionale Inhaltsszenario funktioniert nicht nur nahtlos (wie bei Consumergeräten heute), sondern Sie profitieren auch von den vorteilen kleinerer Downloadgrößen. Darüber hinaus sind Geräte immun gegen die Herausforderung, Windows zu aktualisieren, wenn die Installationssprache des Betriebssystems versehentlich in eine neue Sprache geändert wird. Andernfalls können zukünftige medienbasierte Featureupdates fehlschlagen, wenn das Installationsmedium über eine andere Installationssprache verfügt. Weitere Informationen zu diesem Problem finden Sie unter Upgraden von Windows 10 Geräten mit anderen Installationsmedien als der ursprünglichen Installationssprache des Betriebssystems.

Option 2: Verwenden von WSUS mit UUP-Integration

Ab März 2023 wurde UUP in WSUS und Configuration Manager integriert, um die gleichen optionalen Inhalts- und Akquisitionsvorteile von Windows Update für lokale Verwaltungslösungen zu nutzen. Zum Beispiel:

  • FODs und Sprachen werden automatisch für Geräte migriert, die ein direktes Update mithilfe eines genehmigten Windows 11, Version 22H2-Clientfeatureupdates von WSUS durchführen. Ebenso sind Updates wie das kombinierte kumulative Update, Setupupdates und Updates für sichere Betriebssysteme enthalten und aktuell, basierend auf dem Monat, in dem das Featureupdate genehmigt wurde.

  • Geräte, die ein Upgrade mit einem lokalen Windows-Image durchführen, aber WSUS oder Configuration Manager für die Genehmigung des kombinierten kumulativen Updates verwenden, profitieren von Unterstützung für den optionalen Erwerb von Inhalten im aktualisierten Windows-Betriebssystem sowie die Selbstreparatur des Betriebssystems.

Die für die Aktivierung erforderlichen Inhalte werden über WSUS oder Configuration Manager abgerufen, ohne dass Clientendpunkte eine Internetverbindung erfordern. Um diese Verbesserung zu ermöglichen, ist einmal pro Windows-Hauptversion ein erheblicher Download in das WSUS-Inhaltsverzeichnis oder den Verteilungspunkt erforderlich. Dies umfasst Pakete zur Unterstützung von FOD und Spracherwerb sowie Pakete zur Aktivierung der Selbstreparatur des Betriebssystems aufgrund von Beschädigungen. Weitere Informationen finden Sie unter Planen der WSUS-Bereitstellung.

Option 3: Dynamisches Update aktivieren

Wenn Sie nicht bereit sind, zu Windows Update zu wechseln, ist eine weitere Option das Aktivieren des dynamischen Updates während eines Featureupdates. Sobald ein Windows-Featureupdate gestartet wird, unabhängig davon, ob es sich um ein medienbasiertes Update oder ein WSUS-basiertes Featureupdate handelt, ist dynamisches Update einer der ersten aufgerufenen Schritte. Windows Setup stellt eine Verbindung mit einer url mit Internetzugriff her, die von Microsoft gehostet wird, um dynamische Updateinhalte abzurufen, und wendet diese Updates dann auf die Installationsmedien des Betriebssystems an. Die erworbenen Inhalte umfassen Folgendes:

  • Setupupdates: Korrekturen an Setup.exe Binärdateien oder dateien, die vom Setup für Featureupdates verwendet werden.
  • Updates für sichere Betriebssysteme: Korrekturen für das sichere Betriebssystem , das zum Aktualisieren der Windows-Wiederherstellungsumgebung (WinRE) verwendet wird.
  • Wartungsstapelupdates: Korrekturen, die erforderlich sind, um das Problem mit dem Windows-Wartungsstapel zu beheben und daher erforderlich sind, um das Featureupdate abzuschließen.
  • Neuestes kumulatives Update: Installiert das neueste kumulative Qualitätsupdate.
  • Treiberupdates: Aktuelle Version der anwendbaren Treiber, die bereits von Herstellern in Windows Update veröffentlicht wurden und speziell für dynamische Updates vorgesehen sind.

Zusätzlich zu diesen Updates für das neue Betriebssystem ruft dynamisches Update während des Updatevorgangs optionale Inhalte ab, um sicherzustellen, dass dieser Inhalt auf dem Gerät vorhanden ist, wenn das Update abgeschlossen ist. Obwohl das Gerät nicht mit Windows Update verbunden ist, ruft es Inhalte aus einem in der Nähe befindlichen Microsoft Content Download Network (CDN) ab. Dieser Ansatz behandelt den ersten Problempunkt mit optionalen Inhalten, aber nicht mit benutzerinitiiertem Erwerb. Standardmäßig ist dynamisches Update von Windows Setup aktiviert. Sie können dynamische Updates mithilfe der Option /DynamicUpdate in Windows Setup aktivieren oder deaktivieren. Wenn Sie den wartungsbasierten Ansatz verwenden, können Sie diesen Wert mit setupconfig.inifestlegen. Weitere Informationen finden Sie unter Übersicht über die Windows Setup-Automatisierung .

Dynamische Updates können mit zusätzlichen Optionen konfiguriert werden. Beispielsweise können Sie die Vorteile der optionalen Inhaltsmigration nutzen, ohne automatisch das neueste Qualitätsupdate zu erhalten. Dies ist mit der Option /DynamicUpdate NoLCU von Windows Setup möglich. Danach würden Sie Ihren vorhandenen Prozess zum Testen und Genehmigen monatlicher Updates separat befolgen. Der Nachteil dieses Ansatzes ist, dass das Gerät für das neueste kumulative Update erneut neu gestartet wird, da es während des Featureupdates nicht verfügbar war.

Eine weitere Überlegung bei der Verwendung von dynamischen Updates ist die Auswirkung auf Ihr Netzwerk. Einer der wichtigsten Hindernisse für diesen Ansatz ist die Sorge, dass jedes Gerät diesen Inhalt separat von Microsoft abruft. Setup lädt dynamische Updateinhalte mithilfe der Übermittlungsoptimierung herunter, sofern verfügbar. Für Geräte, die nicht mit dem Internet verbunden sind, ist eine Teilmenge des Dynamischen Updateinhalts über WSUS und den Microsoft-Katalog verfügbar.

Option 4: Anpassen des Windows-Images vor der Bereitstellung

Für viele Organisationen umfasst der Bereitstellungsworkflow eine Configuration Manager Tasksequenz, die ein medienbasiertes Update ausführt. Einige Kunden verfügen entweder über keine Internetverbindung, oder die Konnektivität ist schlecht, sodass sie dynamische Updates nicht aktivieren können. In diesen Fällen wird empfohlen, vor der Bereitstellung optionale Inhalte zu installieren. Diese Aktivität wird manchmal als Anpassen der Installationsmedien bezeichnet.

Sie können das Windows-Image auf folgende Weise anpassen:

  • Anwenden eines kumulativen Updates
  • Anwenden von Updates auf den Wartungsstapel
  • Anwenden von Updates auf Setup.exe Binärdateien oder andere Dateien, die vom Setup für Featureupdates verwendet werden
  • Anwenden von Updates für das sichere Betriebssystem (SafeOS), das für die Windows-Wiederherstellungsumgebung verwendet wird
  • Hinzufügen oder Entfernen von Sprachen
  • Hinzufügen oder Entfernen von Features bei Bedarf

Der Vorteil dieser Option besteht darin, dass das Windows-Image diese zusätzlichen Sprachen, Spracherfahrungsfeatures und andere Features bei Bedarf durch einmalige Updates des Images enthalten kann. Anschließend können Sie sie in einer vorhandenen Tasksequenz oder einer benutzerdefinierten Bereitstellung verwenden, in der Setup.exe beteiligt ist. Der Nachteil dieses Ansatzes ist, dass er eine gewisse Vorbereitung des Images im Voraus erfordert, einschließlich Skripts mit DISM, um die zusätzlichen Pakete zu installieren. Dies bedeutet auch, dass das Image für alle Geräte, die es nutzen, identisch ist und möglicherweise mehr Features enthält, als einige Benutzer benötigen. Weitere Informationen zum Anpassen Ihrer Medien finden Sie unter Aktualisieren Windows 10 Medien mit dynamischen Updatepaketen. Ebenso wie bei dynamischen Updates haben Sie weiterhin eine Lösung für die Migration optionaler Inhalte, aber keine Unterstützung für die benutzerinitiierte optionale Inhaltserfassung. Außerdem gibt es eine Variante dieser Option, bei der medien auf dem Gerät kurz vor der Installation aktualisiert werden. Diese Option ermöglicht die gerätespezifische Imageanpassung basierend auf den derzeit installierten Dateien.

Option 5: Installieren von Sprachfeatures während der Bereitstellung

Eine Teillösung zum Beheben des ersten Problempunkts, bei dem optionale Inhalte während des Upgrades nicht migriert werden können, besteht darin, während des Upgradevorgangs eine Teilmenge optionaler Inhalte einzugeben. Bei diesem Ansatz wird die Windows Setup-Option /InstallLangPacks verwendet, um Sprachpakete und Sprachfunktionen wie die Spracherkennung aus einem Ordner hinzuzufügen, der die Pakete enthält. Mit diesem Ansatz kann ein IT-Experte eine Teilmenge optionaler Inhalte in sein Netzwerk einstufen. Wenn Sie den wartungsbasierten Ansatz verwenden, können Sie InstallLangPacks mit setupconfig.inikonfigurieren. Weitere Informationen finden Sie unter Übersicht über die Windows Setup-Automatisierung.

Wenn Setup ausgeführt wird, werden diese Pakete während der Installation in das neue Betriebssystem eingefügt. Dies kann eine Alternative zum Aktivieren des dynamischen Updates oder zum Anpassen des Betriebssystemimages vor der Bereitstellung sein. Bei diesem Ansatz müssen Sie vorsichtig sein, da die Pakete nicht umbenannt werden können. Darüber hinaus stammen die Inhalte von zwei separaten Releasemedien-ISOs. Der Schlüssel besteht darin, sowohl die FOD-Pakete als auch die FOD-Metadaten .cab aus der FOD-ISO in den Ordner und das architekturspezifische Language Pack .cab Dateien aus der LPLIP-ISO zu kopieren. Wir behandeln InstallLangPacks-Fehler als schwerwiegend und führen ein Rollback für das gesamte Upgrade durch. Die Idee besteht darin, den Benutzer nicht in einem fehlerhaften Zustand zu belassen, da medienbasierte Upgrades keine FOD und Sprachen migrieren (es sei denn, die dynamische Aktualisierung ist aktiviert).

Dieser Ansatz hat einige interessante Vorteile. Das ursprüngliche Windows-Image muss nicht geändert werden, was möglicherweise Zeit und Skripts spart.

Option 6: Installieren optionaler Inhalte nach der Bereitstellung

Diese Option ähnelt Option 4, da Sie das Betriebssystemimage mit optionaleren Inhalten anpassen, nachdem es bereitgestellt wurde. IT-Experten können das Verhalten von Windows Setup erweitern, indem sie ihre eigenen benutzerdefinierten Aktionsskripts während und nach einem Featureupdate ausführen. Weitere Informationen finden Sie unter Ausführen von benutzerdefinierten Aktionen während des Featureupdates . Bei diesem Ansatz können Sie eine gerätespezifische Migration optionaler Inhalte erstellen, indem Sie die optionalen Inhalte erfassen, die im Betriebssystem installiert sind, und diese Liste dann speichern, um denselben optionalen Inhalt im neuen Betriebssystem zu installieren. Wie Option 5 würden Sie intern eine Netzwerkfreigabe hosten, die die Quelle der optionalen Inhaltspakete enthält. Erfassen Sie dann während der Ausführung des Setups auf dem Gerät die Liste der installierten optionalen Inhalte aus dem Quellbetriebssystem, und speichern Sie sie. Später, nach Abschluss des Setups, verwenden Sie die Liste, um den optionalen Inhalt zu installieren, wodurch das Gerät des Benutzers ohne Funktionsverlust verbleibt.

Option 7: Konfigurieren einer alternativen Quelle für optionalen Inhalt

Mehrere der Optionen befassen sich mit Möglichkeiten, optionale Probleme bei der Inhaltsmigration während eines direkten Updates zu beheben. Um den zweiten Problempunkt des einfachen Abrufens optionaler Inhalte im vom Benutzer initiierten Fall zu beheben, können Sie jedes Gerät mithilfe der Gruppenrichtlinie Angeben von Einstellungen für optionale Komponenteninstallation und Komponentenreparatur konfigurieren. Diese Richtlinieneinstellung gibt die Netzwerkspeicherorte an, die für die Reparatur von Betriebssystembeschädigungen und für die Aktivierung optionaler Features verwendet werden, für die die Nutzlastdateien entfernt wurden. Dieser Ansatz hat den Nachteil, dass mehr Inhalte in Ihrem Netzwerk gehostet werden müssen (zusätzlich zum Betriebssystemimage, das Sie möglicherweise noch auf einigen Clients bereitstellen), hat aber den Vorteil, dass Inhalte innerhalb Ihres Netzwerks erworben werden. Einige Erinnerungen zu dieser Richtlinie:

  • Der Dateipfad zur alternativen Quelle muss ein vollqualifizierter Pfad sein. Mehrere Speicherorte können durch ein Semikolon getrennt werden.
  • Diese Einstellung unterstützt nicht die Installation von Sprachpaketen aus einem alternativen Quelldateipfad, nur Features bei Bedarf. Wenn die Richtlinie für das Abrufen von Inhalten aus Windows Update konfiguriert ist, werden Sprachpakete abgerufen.
  • Wenn diese Einstellung nicht konfiguriert oder deaktiviert ist, werden Dateien vom Standardspeicherort Windows Update heruntergeladen, z. B. Windows Update Clientrichtlinien oder WSUS.

Weitere Informationen finden Sie unter Konfigurieren einer Windows-Reparaturquelle und Bereitstellen von Features bei Bedarf und Sprachpaketen bei Verwendung von WSUS oder Configuration Manager.

Weitere Ressourcen

Weitere Informationen zur Unified Update Platform und zu den in diesem Artikel beschriebenen Ansätzen finden Sie in den folgenden Ressourcen:

Beispielskripts

Die Optionen 4 und 6 umfassen die meisten Skripts. Beispielskripts für Option 4 sind bereits vorhanden. Sehen wir uns daher Beispielskripts für Option 6: Installieren optionaler Inhalte nach der Bereitstellung an.

Erstellen eines optionalen Inhaltsrepositorys

Zunächst erstellen wir ein Repository mit optionalen Inhalten und hosten auf einer Netzwerkfreigabe. Bei diesem Inhalt handelt es sich um eine Teilmenge von Inhalten aus den FOD- und Language Pack-ISOs, die im Lieferumfang der einzelnen Versionen enthalten sind. Wir konfigurieren dieses Repository oder Repository nur mit den FODs, die unsere organization benötigen, mithilfe von DISM /Export. Beispielsweise eine Obermenge, die auf der Erfassung optionaler Features basiert, die auf vorhandenen Geräten installiert sind. In diesem Fall schließen wir die Windows Mixed Reality-Funktion aus. Darüber hinaus kopieren wir alle Sprachpakete in den Stamm des Repositorys.

# Declare media for FOD and LPs
$LP_ISO_PATH = "C:\_IMAGE\2004_ISO\CLIENTLANGPACKDVD_OEM_MULTI.iso"
$FOD_ISO_PATH = "C:\_IMAGE\2004_ISO\FOD-PACKAGES_OEM_PT1_amd64fre_MULTI.iso"

# Declare folders
$WORKING_PATH = "C:\_IMAGE\BuildRepo"
$MEDIA_PATH = "C:\_IMAGE\2004_SETUP"

$MAIN_OS_MOUNT = $WORKING_PATH + "\MainOSMount"
$REPO_PATH = $WORKING_PATH + "\Repo"

# Create folders for mounting image optional content repository
if (Test-Path $MAIN_OS_MOUNT) {
    Remove-Item -Path $MAIN_OS_MOUNT -Force -Recurse -ErrorAction stop| Out-Null
}

if (Test-Path $REPO_PATH) {
    Remove-Item -Path $REPO_PATH -Force -Recurse -ErrorAction stop| Out-Null
}

New-Item -ItemType Directory -Force -Path $MAIN_OS_MOUNT -ErrorAction stop| Out-Null
New-Item -ItemType Directory -Force -Path $REPO_PATH -ErrorAction stop| Out-Null

# Mount the main OS, I'll use this throughout the script
Write-Host "Mounting main OS"
Mount-WindowsImage -ImagePath $MEDIA_PATH"\sources\install.wim" -Index 1 -Path $MAIN_OS_MOUNT -ErrorAction stop| Out-Null

# Mount the LP ISO
Write-Host "Mounting LP ISO"
$LP_ISO_DRIVE_LETTER = (Mount-DiskImage -ImagePath $LP_ISO_PATH -ErrorAction stop | Get-Volume).DriveLetter

# Declare language related cabs
$OS_LP_PATH = $LP_ISO_DRIVE_LETTER + ":\x64\langpacks\" + "*.cab"

# Mount the FOD ISO
Write-Host "Mounting FOD ISO"
$FOD_ISO_DRIVE_LETTER = (Mount-DiskImage -ImagePath $FOD_ISO_PATH -ErrorAction stop | Get-Volume).DriveLetter
$FOD_PATH = $FOD_ISO_DRIVE_LETTER + ":\"

# Export the FODs from the ISO that we are interested in
Write-Host "Exporting FODs to Repo"
DISM /image:$MAIN_OS_MOUNT /export-source /source:$FOD_PATH /target:$REPO_PATH `
    /capabilityname:Accessibility.Braille~~~~0.0.1.0 `
    /capabilityname:App.StepsRecorder~~~~0.0.1.0 `
    /capabilityname:App.WirelessDisplay.Connect~~~~0.0.1.0 `
    /capabilityname:Browser.InternetExplorer~~~~0.0.11.0 `
    /capabilityname:DirectX.Configuration.Database~~~~0.0.1.0 `
    /capabilityname:Language.Basic~~~af-za~0.0.1.0 `
    /capabilityname:Language.Basic~~~ar-sa~0.0.1.0 `
    /capabilityname:Language.Basic~~~as-in~0.0.1.0 `
    /capabilityname:Language.Basic~~~az-latn-az~0.0.1.0 `
    /capabilityname:Language.Basic~~~ba-ru~0.0.1.0 `
    /capabilityname:Language.Basic~~~be-by~0.0.1.0 `
    /capabilityname:Language.Basic~~~bg-bg~0.0.1.0 `
    /capabilityname:Language.Basic~~~bn-bd~0.0.1.0 `
    /capabilityname:Language.Basic~~~bn-in~0.0.1.0 `
    /capabilityname:Language.Basic~~~bs-latn-ba~0.0.1.0 `
    /capabilityname:Language.Basic~~~ca-es~0.0.1.0 `
    /capabilityname:Language.Basic~~~cs-cz~0.0.1.0 `
    /capabilityname:Language.Basic~~~cy-gb~0.0.1.0 `
    /capabilityname:Language.Basic~~~da-dk~0.0.1.0 `
    /capabilityname:Language.Basic~~~de-ch~0.0.1.0 `
    /capabilityname:Language.Basic~~~de-de~0.0.1.0 `
    /capabilityname:Language.Basic~~~el-gr~0.0.1.0 `
    /capabilityname:Language.Basic~~~en-au~0.0.1.0 `
    /capabilityname:Language.Basic~~~en-ca~0.0.1.0 `
    /capabilityname:Language.Basic~~~en-gb~0.0.1.0 `
    /capabilityname:Language.Basic~~~en-in~0.0.1.0 `
    /capabilityname:Language.Basic~~~en-us~0.0.1.0 `
    /capabilityname:Language.Basic~~~es-es~0.0.1.0 `
    /capabilityname:Language.Basic~~~es-mx~0.0.1.0 `
    /capabilityname:Language.Basic~~~es-us~0.0.1.0 `
    /capabilityname:Language.Basic~~~et-ee~0.0.1.0 `
    /capabilityname:Language.Basic~~~eu-es~0.0.1.0 `
    /capabilityname:Language.Basic~~~fa-ir~0.0.1.0 `
    /capabilityname:Language.Basic~~~fi-fi~0.0.1.0 `
    /capabilityname:Language.Basic~~~fil-ph~0.0.1.0 `
    /capabilityname:Language.Basic~~~fr-be~0.0.1.0 `
    /capabilityname:Language.Basic~~~fr-ca~0.0.1.0 `
    /capabilityname:Language.Basic~~~fr-ch~0.0.1.0 `
    /capabilityname:Language.Basic~~~fr-fr~0.0.1.0 `
    /capabilityname:Language.Basic~~~ga-ie~0.0.1.0 `
    /capabilityname:Language.Basic~~~gd-gb~0.0.1.0 `
    /capabilityname:Language.Basic~~~gl-es~0.0.1.0 `
    /capabilityname:Language.Basic~~~gu-in~0.0.1.0 `
    /capabilityname:Language.Basic~~~ha-latn-ng~0.0.1.0 `
    /capabilityname:Language.Basic~~~haw-us~0.0.1.0 `
    /capabilityname:Language.Basic~~~he-il~0.0.1.0 `
    /capabilityname:Language.Basic~~~hi-in~0.0.1.0 `
    /capabilityname:Language.Basic~~~hr-hr~0.0.1.0 `
    /capabilityname:Language.Basic~~~hu-hu~0.0.1.0 `
    /capabilityname:Language.Basic~~~hy-am~0.0.1.0 `
    /capabilityname:Language.Basic~~~id-id~0.0.1.0 `
    /capabilityname:Language.Basic~~~ig-ng~0.0.1.0 `
    /capabilityname:Language.Basic~~~is-is~0.0.1.0 `
    /capabilityname:Language.Basic~~~it-it~0.0.1.0 `
    /capabilityname:Language.Basic~~~ja-jp~0.0.1.0 `
    /capabilityname:Language.Basic~~~ka-ge~0.0.1.0 `
    /capabilityname:Language.Basic~~~kk-kz~0.0.1.0 `
    /capabilityname:Language.Basic~~~kl-gl~0.0.1.0 `
    /capabilityname:Language.Basic~~~kn-in~0.0.1.0 `
    /capabilityname:Language.Basic~~~kok-deva-in~0.0.1.0 `
    /capabilityname:Language.Basic~~~ko-kr~0.0.1.0 `
    /capabilityname:Language.Basic~~~ky-kg~0.0.1.0 `
    /capabilityname:Language.Basic~~~lb-lu~0.0.1.0 `
    /capabilityname:Language.Basic~~~lt-lt~0.0.1.0 `
    /capabilityname:Language.Basic~~~lv-lv~0.0.1.0 `
    /capabilityname:Language.Basic~~~mi-nz~0.0.1.0 `
    /capabilityname:Language.Basic~~~mk-mk~0.0.1.0 `
    /capabilityname:Language.Basic~~~ml-in~0.0.1.0 `
    /capabilityname:Language.Basic~~~mn-mn~0.0.1.0 `
    /capabilityname:Language.Basic~~~mr-in~0.0.1.0 `
    /capabilityname:Language.Basic~~~ms-bn~0.0.1.0 `
    /capabilityname:Language.Basic~~~ms-my~0.0.1.0 `
    /capabilityname:Language.Basic~~~mt-mt~0.0.1.0 `
    /capabilityname:Language.Basic~~~nb-no~0.0.1.0 `
    /capabilityname:Language.Basic~~~ne-np~0.0.1.0 `
    /capabilityname:Language.Basic~~~nl-nl~0.0.1.0 `
    /capabilityname:Language.Basic~~~nn-no~0.0.1.0 `
    /capabilityname:Language.Basic~~~nso-za~0.0.1.0 `
    /capabilityname:Language.Basic~~~or-in~0.0.1.0 `
    /capabilityname:Language.Basic~~~pa-in~0.0.1.0 `
    /capabilityname:Language.Basic~~~pl-pl~0.0.1.0 `
    /capabilityname:Language.Basic~~~ps-af~0.0.1.0 `
    /capabilityname:Language.Basic~~~pt-br~0.0.1.0 `
    /capabilityname:Language.Basic~~~pt-pt~0.0.1.0 `
    /capabilityname:Language.Basic~~~rm-ch~0.0.1.0 `
    /capabilityname:Language.Basic~~~ro-ro~0.0.1.0 `
    /capabilityname:Language.Basic~~~ru-ru~0.0.1.0 `
    /capabilityname:Language.Basic~~~rw-rw~0.0.1.0 `
    /capabilityname:Language.Basic~~~sah-ru~0.0.1.0 `
    /capabilityname:Language.Basic~~~si-lk~0.0.1.0 `
    /capabilityname:Language.Basic~~~sk-sk~0.0.1.0 `
    /capabilityname:Language.Basic~~~sl-si~0.0.1.0 `
    /capabilityname:Language.Basic~~~sq-al~0.0.1.0 `
    /capabilityname:Language.Basic~~~sr-cyrl-rs~0.0.1.0 `
    /capabilityname:Language.Basic~~~sr-latn-rs~0.0.1.0 `
    /capabilityname:Language.Basic~~~sv-se~0.0.1.0 `
    /capabilityname:Language.Basic~~~sw-ke~0.0.1.0 `
    /capabilityname:Language.Basic~~~ta-in~0.0.1.0 `
    /capabilityname:Language.Basic~~~te-in~0.0.1.0 `
    /capabilityname:Language.Basic~~~tg-cyrl-tj~0.0.1.0 `
    /capabilityname:Language.Basic~~~th-th~0.0.1.0 `
    /capabilityname:Language.Basic~~~tk-tm~0.0.1.0 `
    /capabilityname:Language.Basic~~~tn-za~0.0.1.0 `
    /capabilityname:Language.Basic~~~tr-tr~0.0.1.0 `
    /capabilityname:Language.Basic~~~tt-ru~0.0.1.0 `
    /capabilityname:Language.Basic~~~ug-cn~0.0.1.0 `
    /capabilityname:Language.Basic~~~uk-ua~0.0.1.0 `
    /capabilityname:Language.Basic~~~ur-pk~0.0.1.0 `
    /capabilityname:Language.Basic~~~uz-latn-uz~0.0.1.0 `
    /capabilityname:Language.Basic~~~vi-vn~0.0.1.0 `
    /capabilityname:Language.Basic~~~wo-sn~0.0.1.0 `
    /capabilityname:Language.Basic~~~xh-za~0.0.1.0 `
    /capabilityname:Language.Basic~~~yo-ng~0.0.1.0 `
    /capabilityname:Language.Basic~~~zh-cn~0.0.1.0 `
    /capabilityname:Language.Basic~~~zh-hk~0.0.1.0 `
    /capabilityname:Language.Basic~~~zh-tw~0.0.1.0 `
    /capabilityname:Language.Basic~~~zu-za~0.0.1.0 `
    /capabilityname:Language.Fonts.Arab~~~und-Arab~0.0.1.0 `
    /capabilityname:Language.Fonts.Beng~~~und-Beng~0.0.1.0 `
    /capabilityname:Language.Fonts.Cans~~~und-Cans~0.0.1.0 `
    /capabilityname:Language.Fonts.Cher~~~und-Cher~0.0.1.0 `
    /capabilityname:Language.Fonts.Deva~~~und-Deva~0.0.1.0 `
    /capabilityname:Language.Fonts.Ethi~~~und-Ethi~0.0.1.0 `
    /capabilityname:Language.Fonts.Gujr~~~und-Gujr~0.0.1.0 `
    /capabilityname:Language.Fonts.Guru~~~und-Guru~0.0.1.0 `
    /capabilityname:Language.Fonts.Hans~~~und-Hans~0.0.1.0 `
    /capabilityname:Language.Fonts.Hant~~~und-Hant~0.0.1.0 `
    /capabilityname:Language.Fonts.Hebr~~~und-Hebr~0.0.1.0 `
    /capabilityname:Language.Fonts.Jpan~~~und-Jpan~0.0.1.0 `
    /capabilityname:Language.Fonts.Khmr~~~und-Khmr~0.0.1.0 `
    /capabilityname:Language.Fonts.Knda~~~und-Knda~0.0.1.0 `
    /capabilityname:Language.Fonts.Kore~~~und-Kore~0.0.1.0 `
    /capabilityname:Language.Fonts.Laoo~~~und-Laoo~0.0.1.0 `
    /capabilityname:Language.Fonts.Mlym~~~und-Mlym~0.0.1.0 `
    /capabilityname:Language.Fonts.Orya~~~und-Orya~0.0.1.0 `
    /capabilityname:Language.Fonts.PanEuropeanSupplementalFonts~~~0.0.1.0 `
    /capabilityname:Language.Fonts.Sinh~~~und-Sinh~0.0.1.0 `
    /capabilityname:Language.Fonts.Syrc~~~und-Syrc~0.0.1.0 `
    /capabilityname:Language.Fonts.Taml~~~und-Taml~0.0.1.0 `
    /capabilityname:Language.Fonts.Telu~~~und-Telu~0.0.1.0 `
    /capabilityname:Language.Fonts.Thai~~~und-Thai~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~af-za~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~bs-latn-ba~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~ca-es~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~cs-cz~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~cy-gb~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~da-dk~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~de-de~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~el-gr~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~en-gb~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~en-us~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~es-es~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~es-mx~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~eu-es~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~fi-fi~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~fr-fr~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~ga-ie~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~gd-gb~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~gl-es~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~hi-in~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~hr-hr~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~id-id~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~it-it~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~ja-jp~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~ko-kr~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~lb-lu~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~mi-nz~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~ms-bn~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~ms-my~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~nb-no~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~nl-nl~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~nn-no~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~nso-za~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~pl-pl~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~pt-br~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~pt-pt~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~rm-ch~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~ro-ro~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~ru-ru~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~rw-rw~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~sk-sk~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~sl-si~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~sq-al~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~sr-cyrl-rs~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~sr-latn-rs~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~sv-se~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~sw-ke~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~tn-za~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~tr-tr~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~wo-sn~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~xh-za~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~zh-cn~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~zh-hk~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~zh-tw~0.0.1.0 `
    /capabilityname:Language.Handwriting~~~zu-za~0.0.1.0 `
    /capabilityname:Language.LocaleData~~~zh-tw~0.0.1.0 `
    /capabilityname:Language.OCR~~~ar-sa~0.0.1.0 `
    /capabilityname:Language.OCR~~~bg-bg~0.0.1.0 `
    /capabilityname:Language.OCR~~~bs-latn-ba~0.0.1.0 `
    /capabilityname:Language.OCR~~~cs-cz~0.0.1.0 `
    /capabilityname:Language.OCR~~~da-dk~0.0.1.0 `
    /capabilityname:Language.OCR~~~de-de~0.0.1.0 `
    /capabilityname:Language.OCR~~~el-gr~0.0.1.0 `
    /capabilityname:Language.OCR~~~en-gb~0.0.1.0 `
    /capabilityname:Language.OCR~~~en-us~0.0.1.0 `
    /capabilityname:Language.OCR~~~es-es~0.0.1.0 `
    /capabilityname:Language.OCR~~~es-mx~0.0.1.0 `
    /capabilityname:Language.OCR~~~fi-fi~0.0.1.0 `
    /capabilityname:Language.OCR~~~fr-ca~0.0.1.0 `
    /capabilityname:Language.OCR~~~fr-fr~0.0.1.0 `
    /capabilityname:Language.OCR~~~hr-hr~0.0.1.0 `
    /capabilityname:Language.OCR~~~hu-hu~0.0.1.0 `
    /capabilityname:Language.OCR~~~it-it~0.0.1.0 `
    /capabilityname:Language.OCR~~~ja-jp~0.0.1.0 `
    /capabilityname:Language.OCR~~~ko-kr~0.0.1.0 `
    /capabilityname:Language.OCR~~~nb-no~0.0.1.0 `
    /capabilityname:Language.OCR~~~nl-nl~0.0.1.0 `
    /capabilityname:Language.OCR~~~pl-pl~0.0.1.0 `
    /capabilityname:Language.OCR~~~pt-br~0.0.1.0 `
    /capabilityname:Language.OCR~~~pt-pt~0.0.1.0 `
    /capabilityname:Language.OCR~~~ro-ro~0.0.1.0 `
    /capabilityname:Language.OCR~~~ru-ru~0.0.1.0 `
    /capabilityname:Language.OCR~~~sk-sk~0.0.1.0 `
    /capabilityname:Language.OCR~~~sl-si~0.0.1.0 `
    /capabilityname:Language.OCR~~~sr-cyrl-rs~0.0.1.0 `
    /capabilityname:Language.OCR~~~sr-latn-rs~0.0.1.0 `
    /capabilityname:Language.OCR~~~sv-se~0.0.1.0 `
    /capabilityname:Language.OCR~~~tr-tr~0.0.1.0 `
    /capabilityname:Language.OCR~~~zh-cn~0.0.1.0 `
    /capabilityname:Language.OCR~~~zh-hk~0.0.1.0 `
    /capabilityname:Language.OCR~~~zh-tw~0.0.1.0 `
    /capabilityname:Language.Speech~~~da-dk~0.0.1.0 `
    /capabilityname:Language.Speech~~~de-de~0.0.1.0 `
    /capabilityname:Language.Speech~~~en-au~0.0.1.0 `
    /capabilityname:Language.Speech~~~en-ca~0.0.1.0 `
    /capabilityname:Language.Speech~~~en-gb~0.0.1.0 `
    /capabilityname:Language.Speech~~~en-in~0.0.1.0 `
    /capabilityname:Language.Speech~~~en-us~0.0.1.0 `
    /capabilityname:Language.Speech~~~es-es~0.0.1.0 `
    /capabilityname:Language.Speech~~~es-mx~0.0.1.0 `
    /capabilityname:Language.Speech~~~fr-ca~0.0.1.0 `
    /capabilityname:Language.Speech~~~fr-fr~0.0.1.0 `
    /capabilityname:Language.Speech~~~it-it~0.0.1.0 `
    /capabilityname:Language.Speech~~~ja-jp~0.0.1.0 `
    /capabilityname:Language.Speech~~~pt-br~0.0.1.0 `
    /capabilityname:Language.Speech~~~zh-cn~0.0.1.0 `
    /capabilityname:Language.Speech~~~zh-hk~0.0.1.0 `
    /capabilityname:Language.Speech~~~zh-tw~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~ar-eg~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~ar-sa~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~bg-bg~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~ca-es~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~cs-cz~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~da-dk~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~de-at~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~de-ch~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~de-de~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~el-gr~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~en-au~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~en-ca~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~en-gb~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~en-ie~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~en-in~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~en-us~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~es-es~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~es-mx~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~fi-fi~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~fr-ca~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~fr-ch~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~fr-fr~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~he-il~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~hi-in~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~hr-hr~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~hu-hu~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~id-id~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~it-it~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~ja-jp~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~ko-kr~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~ms-my~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~nb-no~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~nl-be~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~nl-nl~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~pl-pl~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~pt-br~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~pt-pt~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~ro-ro~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~ru-ru~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~sk-sk~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~sl-si~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~sv-se~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~ta-in~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~th-th~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~tr-tr~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~vi-vn~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~zh-cn~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~zh-hk~0.0.1.0 `
    /capabilityname:Language.TextToSpeech~~~zh-tw~0.0.1.0 `
    /capabilityname:MathRecognizer~~~~0.0.1.0 `
    /capabilityname:Microsoft.Onecore.StorageManagement~~~~0.0.1.0 `
    /capabilityname:Microsoft.WebDriver~~~~0.0.1.0 `
    /capabilityname:Microsoft.Windows.MSPaint~~~~0.0.1.0 `
    /capabilityname:Microsoft.Windows.Notepad~~~~0.0.1.0 `
    /capabilityname:Microsoft.Windows.PowerShell.ISE~~~~0.0.1.0 `
    /capabilityname:Microsoft.Windows.StorageManagement~~~~0.0.1.0 `
    /capabilityname:Microsoft.Windows.WordPad~~~~0.0.1.0 `
    /capabilityname:Msix.PackagingTool.Driver~~~~0.0.1.0 `
    /capabilityname:NetFX3~~ `
    /capabilityname:Network.Irda~~~~0.0.1.0 `
    /capabilityname:OneCoreUAP.OneSync~~~~0.0.1.0 `
    /capabilityname:OpenSSH.Client~~~~0.0.1.0 `
    /capabilityname:OpenSSH.Server~~~~0.0.1.0 `
    /capabilityname:Print.EnterpriseCloudPrint~~~~0.0.1.0 `
    /capabilityname:Print.Fax.Scan~~~~0.0.1.0 `
    /capabilityname:Print.Management.Console~~~~0.0.1.0 `
    /capabilityname:Print.MopriaCloudService~~~~0.0.1.0 `
    /capabilityname:RasCMAK.Client~~~~0.0.1.0 `
    /capabilityname:RIP.Listener~~~~0.0.1.0 `
    /capabilityname:Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.BitLocker.Recovery.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.CertificateServices.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.DHCP.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.Dns.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.FailoverCluster.Management.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.FileServices.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.GroupPolicy.Management.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.IPAM.Client.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.LLDP.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.NetworkController.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.NetworkLoadBalancing.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.RemoteAccess.Management.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.RemoteDesktop.Services.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.ServerManager.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.Shielded.VM.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.StorageMigrationService.Management.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.StorageReplica.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.SystemInsights.Management.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.VolumeActivation.Tools~~~~0.0.1.0 `
    /capabilityname:Rsat.WSUS.Tools~~~~0.0.1.0 `
    /capabilityname:ServerCore.AppCompatibility~~~~0.0.1.0 `
    /capabilityname:SNMP.Client~~~~0.0.1.0 `
    /capabilityname:Tools.DeveloperMode.Core~~~~0.0.1.0 `
    /capabilityname:Tools.Graphics.DirectX~~~~0.0.1.0 `
    /capabilityname:Windows.Client.ShellComponents~~~~0.0.1.0 `
    /capabilityname:Windows.Desktop.EMS-SAC.Tools~~~~0.0.1.0 `
    /capabilityname:WMI-SNMP-Provider.Client~~~~0.0.1.0 `
    /capabilityname:XPS.Viewer~~~~0.0.1.0

    # This one is large, lets skip for now
    #/capabilityname:Analog.Holographic.Desktop~~~~0.0.1.0 `


# Copy language caps to the repo
Copy-Item -Path $OS_LP_PATH -Destination $REPO_PATH -Force -ErrorAction stop | Out-Null

# Dismount OS image
Dismount-WindowsImage -Path $MAIN_OS_MOUNT -Discard -ErrorAction ignore | Out-Null

# Dismount ISO images
Write-Host "Dismounting ISO images"
Dismount-DiskImage -ImagePath $LP_ISO_PATH -ErrorAction ignore | Out-Null
Dismount-DiskImage -ImagePath $FOD_ISO_PATH -ErrorAction ignore | Out-Null

Speichern optionaler Inhalte im Quellbetriebssystem

Um den optionalen Inhaltsstatus im Quellbetriebssystem zu speichern, erstellen wir ein benutzerdefiniertes Aktionsskript, das vor der Installation des Betriebssystems ausgeführt wird. In diesem Skript speichern wir optionale Features und Sprachressourcen in einer Datei. Außerdem erstellen wir eine lokale Kopie des Repositorys mit nur den Dateien, die basierend auf den auf dem Quellbetriebssystem installierten Sprachen benötigt werden. Diese Aktion schränkt die zu kopierenden Dateien ein.

$OUTPUT_PATH = "C:\TEMP\"
$LOG_PATH = $OUTPUT_PATH + "log.txt"
$OUTPUT_PATH = "C:\TEMP\"
$LOG_PATH = $OUTPUT_PATH + "log.txt"
$LANG_PATH = $OUTPUT_PATH + "sourceLang.txt"
$CAP_PATH = $OUTPUT_PATH + "sourceCapability.txt"
$OSVERSION_PATH = $OUTPUT_PATH + "sourceVersion.txt"
$REPO_PATH = "Z:\Repo\"
$LOCAL_REPO_PATH = $OUTPUT_PATH + "Local_Repo\"

Function Get-TS { return "{0:HH:mm:ss}" -f (Get-Date) }

Function Log
{
	param (
        [Parameter(Mandatory=$True)]
        [string]$MESSAGE
	)

    $M = "$(Get-TS): PreInstall: $MESSAGE"
    Write-Host $M
    Add-Content -Path $LOG_PATH -Value $M

 }

Function IsLangFile
{
	param (
        [Parameter(Mandatory=$True)]
        [string]$PATH
	)

    if (($PATH -match '[-_~]ar[-_~]') -or ($PATH -match '[-_~]bg[-_~]') -or ($PATH -match '[-_~]cs[-_~]') -or `
        ($PATH -match '[-_~]da[-_~]') -or ($PATH -match '[-_~]de[-_~]') -or ($PATH -match '[-_~]el[-_~]') -or `
        ($PATH -match '[-_~]en[-_~]') -or ($PATH -match '[-_~]es[-_~]') -or ($PATH -match '[-_~]et[-_~]') -or `
        ($PATH -match '[-_~]fi[-_~]') -or ($PATH -match '[-_~]fr[-_~]') -or ($PATH -match '[-_~]he[-_~]') -or `
        ($PATH -match '[-_~]hr[-_~]') -or ($PATH -match '[-_~]hu[-_~]') -or ($PATH -match '[-_~]it[-_~]') -or `
        ($PATH -match '[-_~]ja[-_~]') -or ($PATH -match '[-_~]ko[-_~]') -or ($PATH -match '[-_~]lt[-_~]') -or `
        ($PATH -match '[-_~]lv[-_~]') -or ($PATH -match '[-_~]nb[-_~]') -or ($PATH -match '[-_~]nl[-_~]') -or `
        ($PATH -match '[-_~]pl[-_~]') -or ($PATH -match '[-_~]pt[-_~]') -or ($PATH -match '[-_~]ro[-_~]') -or `
        ($PATH -match '[-_~]ru[-_~]') -or ($PATH -match '[-_~]sk[-_~]') -or ($PATH -match '[-_~]sl[-_~]') -or `
        ($PATH -match '[-_~]sv[-_~]') -or ($PATH -match '[-_~]th[-_~]') -or ($PATH -match '[-_~]tr[-_~]') -or `
        ($PATH -match '[-_~]uk[-_~]') -or ($PATH -match '[-_~]zh[-_~]') -or ($PATH -match '[-_~]sr[-_~]')) {
        return $True
    }
    else {
        return $False
    }
 }

# Remove the log
Remove-Item -Path $LOG_PATH -Force -ErrorAction ignore | Out-Null
Log "Starting"

# Remove state files, keep repo if it exists
Remove-Item -Path $LANG_PATH -Force -ErrorAction ignore | Out-Null
Remove-Item -Path $CAP_PATH -Force -ErrorAction ignore | Out-Null
Remove-Item -Path $OSVERSION_PATH -Force -ErrorAction ignore | Out-Null

# Get OS version, to use later for detecting compat scans versus OS installation
$OSINFO = Get-CimInstance Win32_OperatingSystem
Log "OS Version: $($OSINFO.Version)"
Add-Content -Path $OSVERSION_PATH -Value $OSINFO.Version

# Get installed languages from international settings
$INTL = DISM.exe /Online /Get-Intl /English

# Save only output lines with installed languages
$LANGUAGES = $INTL | Select-String -SimpleMatch 'Installed language(s)'

# Replace with null so we have a simple list of language codes
$LANGUAGES = $LANGUAGES | ForEach-Object {$_.Line.Replace("Installed language(s): ","")}

# Save System Language, save only output line with default system language
$SYSLANG = $INTL | Select-String -SimpleMatch 'Default system UI language'

# Replace with null so we have the language code
$SYSLANG = $SYSLANG | ForEach-Object {$_.Line.Replace("Default system UI language : ","")}

# Save these languages
Log "Default system UI language on source OS: $($SYSLANG)"
ForEach ($ITEM in $LANGUAGES) {
    Log "Installed language on source OS: $($ITEM)"
    Add-Content -Path $LANG_PATH -Value $ITEM
}

# Get and save installed packages, we'll use this for debugging
$PACKAGES = Get-WindowsPackage -Online
ForEach ($ITEM in $PACKAGES) {
    if($ITEM.PackageState -eq "Installed") {
        Log "Package $($ITEM.PackageName) is installed"
    }
}

# Get and save capabilities
$CAPABILITIES = Get-WindowsCapability -Online
ForEach ($ITEM in $CAPABILITIES) {
    if($ITEM.State -eq "Installed") {
        Log "Capability $($ITEM.Name) is installed"
        Add-Content -Path $CAP_PATH -Value $ITEM.Name
    }
}

# Copy a subset of the Repo files locally, all neutral files and the languages needed
$REPO_FILES = Get-ChildItem $REPO_PATH -file -Recurse
ForEach ($FILE in $REPO_FILES) {
    $PATH = ($FILE.DirectoryName + "\") -Replace [Regex]::Escape($REPO_PATH), $LOCAL_REPO_PATH
    If (!(Test-Path $Path)) {
        New-Item -ItemType Directory -Path $PATH -Force | Out-Null
    }
    If ((IsLangFile $FILE.Name)) {

        # Only copy those files where we need the primary languages from the source OS
        ForEach ($ITEM in $LANGUAGES) {
            if ($FILE.Name -match $Item) {

                If (!(Test-Path (Join-Path $Path $File.Name))) {
                    Copy-Item $FILE.FullName -Destination $PATH -Force
                    Log "Copied file $($FILE.FullName) to local repository"
                }
                else {
                    Log "File $($FILE.Name) already exists in local repository"
                }
            }
        }
    } Else {

        # Copy all 'neutral files' and those language specific that are not in the core 38
        If (!(Test-Path (Join-Path $Path $File.Name))) {
            Copy-Item $FILE.FullName -Destination $PATH -Force
            Log "Copied file $($FILE.FullName) to local repository"
        }
        else {
            Log "File $($FILE.Name) already exists in local repository"
        }
    }
}

Log ("Exiting")

Hinzufügen optionaler Inhalte im Zielbetriebssystem

Nachdem das Setup erfolgreich abgeschlossen wurde, verwenden wir success.cmd, um den optionalen Inhaltszustand aus dem Quellbetriebssystem abzurufen und nur dann im neuen Betriebssystem zu installieren, wenn dieser fehlt. Wenden Sie dann das neueste monatliche Update als letzten Schritt an.

$OUTPUT_PATH = "C:\TEMP\"
$LOG_PATH = $OUTPUT_PATH + "log.txt"
$LANG_PATH = $OUTPUT_PATH + "sourceLang.txt"
$CAP_PATH = $OUTPUT_PATH + "sourceCapability.txt"
$OSVERSION_PATH = $OUTPUT_PATH + "sourceVersion.txt"
$LOCAL_REPO_PATH = $OUTPUT_PATH + "Local_Repo\"
$LCU_PATH = $OUTPUT_PATH + "Windows10.0-KB4565503-x64_PSFX.cab"
$PENDING = $false

Function Get-TS { return "{0:HH:mm:ss}" -f (Get-Date) }

Function Log
{
	param (
        [Parameter(Mandatory=$True)]
        [string]$MESSAGE
	)

    $M = "$(Get-TS): PostInstall: $MESSAGE"
    Write-Host $M
    Add-Content -Path $LOG_PATH -Value $M

 }

Log "Starting"

# Get OS version
$OSINFO = Get-CimInstance Win32_OperatingSystem
Log "OS Version: $($OSINFO.Version)"

# Check for source OS state, just to be sure
if (!(Test-Path $LANG_PATH) -or !(Test-Path $CAP_PATH) -or !(Test-Path $OSVERSION_PATH) ) {
    Log "Source OS state is missing."
}

# If this script is executing and the OS version hasn't changed, let's exit out.
else {

    # Retrive OS version from source OS
    $SOURCE_OSVERSION  = Get-Content -Path $OSVERSION_PATH
    if ($OSINFO.Version -eq $SOURCE_OSVERSION) {
        Log "OS Version hasn't changed."
    }

    else {

        # Retrive language list from source OS
        $SOURCE_LANGUAGES  = Get-Content -Path $LANG_PATH

        # Get installed languages from International Settings
        $INTL = DISM.exe /Online /Get-Intl /English

        # Save System Language, save only output line with default system language
        $SYS_LANG = $INTL | Select-String -SimpleMatch 'Default system UI language'

        # Replace with null so we have the language code
        $SYS_LANG = $SYS_LANG | ForEach-Object {$_.Line.Replace("Default system UI language : ","")}

        # Get and save installed packages, we'll use this for debugging
        $PACKAGES = Get-WindowsPackage -Online
        ForEach ($ITEM in $PACKAGES) {
            if($ITEM.PackageState -eq "Installed") {
                Log "Package $($ITEM.PackageName) is installed"
            }
        }

        # Loop through source OS languages, and install if missing on target OS
        ForEach ($SOURCE_ITEM in $SOURCE_LANGUAGES) {
            if ($SOURCE_ITEM -ne $SYS_LANG) {

                # add missing languages except the system language
                Log "Adding language Microsoft-Windows-Client-Language-Pack_x64_$($SOURCE_ITEM).cab"
                try {
                    Add-WindowsPackage -Online -PackagePath "$($LOCAL_REPO_PATH)\Microsoft-Windows-Client-Language-Pack_x64_$($SOURCE_ITEM).cab" -ErrorAction stop | Out-Null
                }
                catch {
                    Log $_.Exception.Message
                }
            }
        }

        # Retrieve capabilities from source OS and target OS
        $SOURCE_CAPABILITIES  = Get-Content -Path $CAP_PATH
        $CAPABILITIES = Get-WindowsCapability -Online

        # Loop through source OS capabilities, and install if missing on target OS
        ForEach ($SOURCE_ITEM in $SOURCE_CAPABILITIES) {
            $INSTALLED = $false
            ForEach ($ITEM in $CAPABILITIES) {
                if ($ITEM.Name -eq $($SOURCE_ITEM)) {
                    if ($ITEM.State -eq "Installed") {
                        $INSTALLED = $true
                        break
                    }
                }
            }

            # Add if not already installed
            if (!($INSTALLED)) {
                Log "Adding capability $SOURCE_ITEM"
                try {
                    Add-WindowsCapability -Online -Name $SOURCE_ITEM -Source $LOCAL_REPO_PATH -ErrorAction stop | Out-Null
                }
                catch {
                    Log $_.Exception.Message
                }
            }
            else {
                Log "Capability $SOURCE_ITEM is already installed"
            }
        }

        # Add LCU, this is required after adding FODs and languages
        Log ("Adding LCU")
        Add-WindowsPackage -Online -PackagePath $LCU_PATH -NoRestart

        # Get packages, we'll use this for debugging and to see if we need to restart to install
        $PACKAGES = Get-WindowsPackage -Online
        ForEach ($ITEM in $PACKAGES) {
            Log "Package $($ITEM.PackageName) is $($ITEM.PackageState)"
            if ($ITEM.PackageState -eq "InstallPending") {
                $PENDING = $true
            }
        }
    }
}

# Remove local repository and state files
Remove-Item -Path $LANG_PATH -Force -ErrorAction ignore | Out-Null
Remove-Item -Path $CAP_PATH -Force -ErrorAction ignore | Out-Null
Remove-Item -Path $OSVERSION_PATH -Force -ErrorAction ignore | Out-Null
Remove-Item -Path $LOCAL_REPO_PATH -Force -Recurse -ErrorAction ignore | Out-Null

# Restarting the computer to let setup process to exit cleanly
if ($PENDING) {
    Log ("Install pending packages exists, restarting in 10 seconds")
    Start-Process -FilePath cmd -ArgumentList "/C shutdown /r /t 10 /f"
}

Log ("Exiting")