Updating Windows 10 media with Dynamic Update packages

This post has been republished via RSS; it originally appeared at: New blog articles in Microsoft Tech Community.

In the recent blog entitled The benefits of Windows 10 Dynamic Update, Monika Sinha provided an overview of Dynamic Update, the benefits of enabling it, how it works, and how to manage this content in a managed environment.

 

For IT pros that want to have these updates applied to their Windows 10 image prior to deployment, they need to understand how Dynamic Update packages can be acquired and applied to their image. This blog will walk through the steps for acquiring and applying Dynamic Update packages, showcasing a sample PowerShell script.

Dynamic Update refresher

As soon as a Windows 10 feature update initiates, whether from media or a Windows Update service-connected environment, Dynamic Update is one of the first steps invoked. Windows 10 Setup reaches out to an Internet-facing URL hosted by Microsoft to fetch Dynamic Update content, then applies those updates to your OS installation media.

 

Content acquired includes:

 

  • Setup Updates: Fixes to Setup binaries or any files that Setup uses for feature updates.
  • Safe OS Updates: Fixes for the ‘safe OS’ that are used to update Windows recovery environment (WinRE).
  • Servicing Stack Updates: Fixes that are necessary to address the Windows 10 servicing stack issue and thus required to complete the feature update.
  • Latest Cumulative Update: Installs the latest cumulative quality update.
  • Driver Updates: Latest version of applicable drivers that have already been published by manufacturers into Windows Update and specifically targeted for Dynamic Update.

 

In addition to these updates, Dynamic Update will preserve Language Pack (LP) and Features on Demand (FODs) content during the upgrade process. These are not updates to LPs and FODs, but reacquisition to ensure the user has these elements present with the update completes.

 

For some environments, enabling acquired Dynamic Update content and installing that content on the device is not an option. For example, the device may not have internet connectivity. If one is performing a media-based feature update, most Dynamic Update content can be acquired and applied to the image before initiating setup on the device.

 

Let’s briefly walk through the high-level steps. Then, we’ll look at how to perform these steps using a PowerShell script.

Acquiring the content

Visit the Microsoft Update Catalog and acquire the Dynamic Update cumulative content packages used to apply to the image. At the main search bar, searching for “1809 Dynamic Update” will show a listing as follows:

 

It appears that there is a Safe OS Dynamic Update available to download. However, what about the other packages? To understand how to map these search results requires closer inspection of each Title, Product and Description.

 

The below table summaries pay special attention to the highlighted strings that will differentiate each type of Dynamic Update package:

 

DU Content

Title

Product

Description

SafeOS DU

2019-08 Dynamic Update …

Windows 10 Dynamic Update,Windows Safe OS Dynamic Update

ComponentUpdate:

Setup DU

2019-08 Dynamic Update …

Windows 10 Dynamic Update

SetupUpdate:

LCU

2019-08 Cumulative Update for Windows 10

Windows 10

Install this update to resolve issues in Windows …

SSU DU

2019-09 Servicing Stack Update for Windows 10

Windows 10 …

Install this update to resolve issues in Windows …

 

In order to customize the OS image with additional languages or FODs, have the OS supplemental media ISOs available, which are downloadable from the Microsoft Volume Licensing Service Center. For example, since Dynamic Update will be disabled for your devices, and should users require specific FODs, these can be preinstalled into the image.

 

Patching the Windows 10 installation media

Now we can work on how the packages and acquired supplemental media can be used to patch Windows 10 OS media. To get started, let’s look at the high-level steps we’ll perform using PowerShell.

 

The table below shows the steps (as rows) that are executed against a target (as columns). Many of these tasks are repeated for target. For example, tasks that are repeated for each of the multiple Windows image files, such as applying SSU DU, cleaning the image, and exporting the image. The targets of these actions are as follows:

 

  • WinPE: The Windows Preinstallation Environment (WinPE) is a small operating system used to install, deploy, and repair Windows 10 desktop editions, Windows Server, and other Windows operating systems. From WinPE, it’s possible to set up a hard drive before installing Windows, install Windows by using apps or scripts from a network or a local drive, or capture and apply Windows images. Further, it’s possible to modify the Windows operating system while it's not running, set up automatic recovery tools, recover data from unbootable devices, and add a custom shell or GUI to automate tasks.
  • WinRE: The Windows Recovery Environment (WinRE) repair common causes of unbootable operating systems. WinRE is based on Windows Preinstallation Environment and can be customized with additional drivers, languages, Windows PE Optional Components, and other troubleshooting or diagnostic tools.
  • Main OS: The main OS is one or more Windows 10 editions stored within \sources\install.wim.
  • Media: Media in the table below represents the complete collection of files and folders in the Windows 10 installation media. For example, \sources folder, \boot folder, setup.exe, etc.

 

 

WinRE

(winre.wim)

WinPE (boot.wim)

Main OS (install.wim)

New Media

Add SSU DU

1

9

18

 

Add Lang Pack

2

10

19

 

Add Localized Optional Components

3

11

   

Add Font Support

4

12

   

Add TTS Support

5

13

   

Update Lang.ini

 

14

   

Add FOD

   

20

 

Add .Net Cumulative Updates

   

21

 

Add Safe OS DU

6

     

Add Setup DU

     

25

Add LCU

 

15

22

 

Clean Image

7

16

23

 

Export Image

8

17

24

 

 

 

Handling multiple Windows editions

The main OS (install.wim) contains multiple editions of Windows 10. It’s possible that only a patch for the edition is required to deploy, based on the index. Or, if needed, loop through all editions and patch. Further, ensure that languages are installed before optional features, and the LCU is always applied last.

Customizing Windows with additional languages and features

Although not required from a patching perspective, this is an opportunity to customize the image with languages and FODs. We highlight this to ensure the correct sequencing is used. Applying the patches, followed by language additions, then by FOD additions, and lastly finish with the LCU. In the script below, we will be installing a single language, in this case Japanese (ja-JP). Since this is a lp.cab backed language, there isn’t a need to add a Language Experience Pack (LXP). We’ll add Japanese to both the main OS and to the recovery environment to allow the user to see the recovery screens in Japanese. This includes adding localized versions of the packages currently installed in the recovery image.

Using PowerShell to apply DU content to an existing Windows 10 image

In this section, we’ll take the steps above and show how they can be executed using PowerShell. The code shown is for illustration purposes only, and thus lacks error handling. To get started, the PowerShell script assumes the following content is stored locally with the following folder structure:

 

Folder

Description

C:\mediaRefresh

Parent folder that contains the PowerShell script

C:\mediaRefresh\oldMedia

Folder that contains the original media that will be refreshed. For example, contains setup.exe, and \sources folder.

C:\mediaRefresh\newMedia

Folder that will contain the patched media. It is copied from \oldMedia, then used as the target for all patching and cleanup operations.

Getting started

Start the script by declaring global variables and creating folders to use for mounting images. Then, make a copy of the original media, from \oldMedia to \newMedia, keeping the original media in case there is a script error and thus we can start over from a known state. Also, it will provide a comparison of old versus new media to evaluate changes. To ensure the new media updates, ensure they are not read only.

 

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

 

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

 

# Declare media for FOD and LPs

$FOD_ISO_PATH = "C:\mediaRefresh\packages\FOD-PACKAGES_OEM_PT1_amd64fre_MULTI.iso"

$LP_ISO_PATH = "C:\mediaRefresh\packages\CLIENTLANGPACKDVD_OEM_MULTI.iso"

 

# Declare language for showcasing adding optional localized components

$LANG = "ja-jp"

$LANG_FONT_CAPABILITY = "jpan"

 

# 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”

 

# Declare folders for mounted images and temp files

$WORKING_PATH = "C:\mediaRefresh\temp"

$MEDIA_OLD_PATH = "C:\mediaRefresh\oldMedia"

$MEDIA_NEW_PATH = "C:\mediaRefresh\newMedia"

$MAIN_OS_MOUNT = $WORKING_PATH + "\MainOSMount”

$WINRE_MOUNT = $WORKING_PATH + "\WinREMount”

$WINPE_MOUNT = $WORKING_PATH + "\WinPEMount”

 

# Mount the LP ISO

Write-Host "$(Get-TS): Mounting LP ISO"

$LP_ISO_DRIVE_LETTER = (Mount-DiskImage -ImagePath $LP_ISO_PATH -ErrorAction stop | Get-Volume).DriveLetter

 

# Declare language related cabs

$WINPE_OC_PATH = Join-Path $LP_ISO_DRIVE_LETTER":" -ChildPath "Windows Preinstallation Environment" | Join-Path -ChildPath "x64" | Join-Path -ChildPath "WinPE_OCs"

$WINPE_OC_LANG_PATH = Join-Path $WINPE_OC_PATH $LANG

$WINPE_OC_LANG_CABS = Get-ChildItem $WINPE_OC_LANG_PATH -name

$WINPE_OC_LP_PATH = Join-Path $WINPE_OC_LANG_PATH "lp.cab"

$WINPE_FONT_SUPPORT_PATH = Join-Path $WINPE_OC_PATH "WinPE-FontSupport-$LANG.cab"

$WINPE_SPEECH_TTS_PATH = Join-Path $WINPE_OC_PATH "WinPE-Speech-TTS.cab"

$WINPE_SPEECH_TTS_LANG_PATH = Join-Path $WINPE_OC_PATH "WinPE-Speech-TTS-$LANG.cab"

$OS_LP_PATH = $LP_ISO_DRIVE_LETTER + ":\x64\langpacks\" + "Microsoft-Windows-Client-Language-Pack_x64_" + $LANG + ".cab"

 

# Mount the FOD ISO

Write-Host "$(Get-TS): Mounting FOD ISO"

$FOD_ISO_DRIVE_LETTER = (Mount-DiskImage -ImagePath $FOD_ISO_PATH -ErrorAction stop | Get-Volume).DriveLetter

$FOD_PATH = $FOD_ISO_DRIVE_LETTER + ":\"

 

# 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, patched media.

Write-Host "$(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 }

Patch WinRE

Start by assuming we’re only patching a single edition, indicated by Index = 1 (Windows 10 Education Edition). Then, mount the image, save winre.wim to the working folder, and mount it. To get started, apply SSU DU, given its components are used for updating other components. Since we are optionally adding Japanese, add the language pack to the image, and install the Japanese versions of all optional components already installed in winre.wim. Then, apply the Safe OS DU package.

 

To finish, clean and export the image to reduce the image size. Note: Skip adding the LCU to winre.wim because it contains unnecessary components in the recovery environment. The components that are updated and applicable are contained within the Safe OS DU package. This also helps to keep the image small.

 

# Mount the main OS, I'll use this throughout the script

Write-Host "$(Get-TS): Mounting main OS"

Mount-WindowsImage -ImagePath $MEDIA_NEW_PATH"\sources\install.wim” -Index 1 -Path $MAIN_OS_MOUNT -ErrorAction stop| Out-Null

 

#

# Patch Windows Recovery Environment (WinRE)

#

Copy-Item -Path $MAIN_OS_MOUNT"\windows\system32\recovery\winre.wim” -Destination $WORKING_PATH"\winre.wim” -Force -Recurse -ErrorAction stop | Out-Null

Write-Host "$(Get-TS): Mounting WinRE"

Mount-WindowsImage -ImagePath $WORKING_PATH"\winre.wim” -Index 1 -Path $WINRE_MOUNT -ErrorAction stop | Out-Null

 

# Add SSU

Write-Host "$(Get-TS): Adding package $SSU_PATH"

Add-WindowsPackage -Path $WINRE_MOUNT -PackagePath $SSU_PATH -ErrorAction stop | Out-Null

 

#

# Optional: Add the language to recovery environment

#

# Install lp.cab cab

Write-Host "$(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 component 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-Host "$(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-Host "$(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-Host "$(Get-TS): Adding package $WINPE_SPEECH_TTS_PATH"

       Add-WindowsPackage -Path $WINRE_MOUNT -PackagePath $WINPE_SPEECH_TTS_PATH -ErrorAction stop | Out-Null

          

       Write-Host "$(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-Host "$(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-Host "$(Get-TS): Performing image cleanup on WinRE"

DISM /image:$WINRE_MOUNT /cleanup-image /StartComponentCleanup | Out-Null

 

# Dismount

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

 

# Export

Write-Host "$(Get-TS): Exporting image to $WORKING_PATH\winre2.wim”

Export-WindowsImage -SourceImagePath $WORKING_PATH"\winre.wim” -SourceIndex 1 -DestinationImagePath $WORKING_PATH"\winre2.wim” -ErrorAction stop | Out-Null

Move-Item -Path $WORKING_PATH"\winre2.wim” -Destination $WORKING_PATH"\winre.wim” -Force -ErrorAction stop | Out-Null

Patch WinPE.

Following a similar pattern as above, but this time mount boot.wim, apply the packages with LCU going last, and save. This is done for all images inside of boot.wim, typically two images. Again, start by applying the SSU Dynamic Update. Since we are customizing this media with Japanese, again install the language pack from the WinPE folder on the language pack ISO. Additionally, add font support and text to speak (TTS) support. Since we are adding a new language, rebuild lang.ini, used to identify languages installed in the image. Finally, clean and export boot.wim, and copy back to the new media.

 

#

# Patch 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) {

 

   # Patch WinPE

   Write-Host "$(Get-TS): Mounting WinPE"

   Mount-WindowsImage -ImagePath $MEDIA_NEW_PATH“\sources\boot.wim” -Index $IMAGE.ImageIndex -Path $WINPE_MOUNT -ErrorAction stop | Out-Null

 

   # Add SSU

   Write-Host "$(Get-TS): Adding package $SSU_PATH"

   Add-WindowsPackage -Path $WINPE_MOUNT -PackagePath $SSU_PATH -ErrorAction stop | Out-Null

      

   # Install lp.cab cab

   Write-Host "$(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 component 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-Host "$(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-Host "$(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-Host "$(Get-TS): Adding package $WINPE_SPEECH_TTS_PATH"

           Add-WindowsPackage -Path $WINPE_MOUNT -PackagePath $WINPE_SPEECH_TTS_PATH -ErrorAction stop | Out-Null

          

           Write-Host "$(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-Host "$(Get-TS): Updating lang.ini"

       DISM /image:$WINPE_MOUNT /Gen-LangINI /distribution:$WINPE_MOUNT | Out-Null

   }  

  

   # Add LCU

   Write-Host "$(Get-TS): Adding package $LCU_PATH"

   Add-WindowsPackage -Path $WINPE_MOUNT -PackagePath $LCU_PATH -ErrorAction stop | Out-Null

 

   # Perform image cleanup

   Write-Host "$(Get-TS): Performing image cleanup on WinPE"

   DISM /image:$WINPE_MOUNT /cleanup-image /StartComponentCleanup | Out-Null

 

   # Dismount

   Dismount-WindowsImage -Path $WINPE_MOUNT -Save -ErrorAction stop |Out-Null

 

   #Export WinPE

   Write-Host "$(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

Patch the main OS

When moving on to the main OS, note that it is already mounted from above. again start by applying SSU Dynamic Update. Then, add in Japanese language support. Next, Iadd the Japanese language FOD. Unlike the DU packages, leverage Add-WindowsCapability to add FODs. For a full list of FODs, and their associated capability name, see Available Features on Demand.

 

Now is the time to add enable other optional components or add other FODs. Further, if the FOD has an associated cumulative update (e.g. .Net), apply these now. Proceed with applying the LCU. As a rule, this always get applied last. Finally, clean and export the image.

 

#

# Patch Main OS

#

 

# Add SSU

Write-Host "$(Get-TS): Adding package $SSU_PATH"

Add-WindowsPackage -Path $MAIN_OS_MOUNT -PackagePath $SSU_PATH -ErrorAction stop | Out-Null

 

# Optional: Add language to main OS

Write-Host "$(Get-TS): Adding package $OS_LP_PATH"

Add-WindowsPackage -Path $MAIN_OS_MOUNT -PackagePath $OS_LP_PATH -ErrorAction stop | Out-Null

 

# Optional: Add a FODs to the image

Write-Host "$(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-Host "$(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-Host "$(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-Host "$(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-Host "$(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-Host "$(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 optional components, I'd add these here. For example, .Net 3.5

# Note: If I have updates for optional components, I'd add these here. For example, Cumulative Update for .Net 3.5

 

# Add LCU

Write-Host "$(Get-TS): Adding package $LCU_PATH"

Add-WindowsPackage -Path $MAIN_OS_MOUNT -PackagePath $LCU_PATH -ErrorAction stop | Out-Null

 

# Copy our updated recovery image from earlier into the main OS

# Note: If I were updating more than 1 edition, I'd want to copy the same recovery image file

# into each edition to enable single instancing

Copy-Item -Path $WORKING_PATH"\winre.wim” -Destination $MAIN_OS_MOUNT"\windows\system32\recovery\winre.wim” -Force -Recurse -ErrorAction stop | Out-Null

 

# Perform image cleanup

Write-Host "$(Get-TS): Performing image cleanup on main OS"

DISM /image:$MAIN_OS_MOUNT /cleanup-image /StartComponentCleanup | Out-Null

 

# Dismount

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

 

# Export

Write-Host "$(Get-TS): Exporting image to $WORKING_PATH\install2.wim”

Export-WindowsImage -SourceImagePath $MEDIA_NEW_PATH“\sources\install.wim” -SourceIndex 1 -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

 

Patch remaining media files

Next, update the setup files. This is a simple copy of the individual files in the Setup DU package to the new media. This step brings an updated setup.exe as needed, along with the latest compatibility database, and replacement component manifests.

 

#

# Patch remaining files on media

#

 

# Add Setup DU by copy the files from the package into the newMedia

Write-Host "$(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

 

 

Finishing up!

As a last step, we’ll remove our working folder of temporary files, and unmount our language pack and FOD ISOs.

 

#

# Perform final cleanup

#

 

# Remove our working folder

Remove-Item -Path $WORKING_PATH -Recurse -Force -ErrorAction stop | Out-Null

 

# Dismount ISO images

Write-Host "$(Get-TS): Dismounting ISO images"

Dismount-DiskImage -ImagePath $LP_ISO_PATH -ErrorAction stop | Out-Null

Dismount-DiskImage -ImagePath $FOD_ISO_PATH -ErrorAction stop |Out-Null

 

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

Learn more

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.