OSDeploy PSModule and site pages are currently in preview until mid-September
For the complete documentation index, see llms.txt. This page is also available as Markdown.

Windows ESD Catalogs

Understand how OSDeploy uses the Windows ESD catalog to select, download, cache, and verify Windows 11 media.

This article steps through the code behind Update-OSDeployCoreESD to show how OSDeploy turns a Windows ESD catalog into a verified file in the local cache.

The catalog is the function's source of truth. It connects a Windows release, language, edition, and architecture to a specific ESD file on the Microsoft Content Delivery Network.

The catalog is included with the OSDeploy module under:

OSDeploy\core\operatingsystems\

Each XML file describes one Windows release. The catalog file name contains the Windows build and release:

26200.8653-win11-25h2.xml
File name segment
Meaning

26200.8653

Windows build and revision

win11

Windows 11

25h2

Windows 11, version 25H2

Catalog names change when newer media is tested and added to OSDeploy. The function sorts the bundled catalog files by name and selects the first one.

The catalog contains metadata and Microsoft download URLs. It does not contain the Windows installation media itself.

Follow the Code Path

The function handles the catalog in three stages before a download begins:

  1. Resolve and parse the latest bundled catalog.

  2. Build target records and match them against the catalog.

  3. Check the cache and URL before asking the user to download.

After confirmation, a separate download loop resumes transfers, handles retries, and verifies SHA256. Keeping discovery separate from transfer allows the function to evaluate every requested architecture before downloading any file.

Resolve the Catalog

The function starts from $script:OSDeployModuleBase, which points to the installed module. It enumerates the XML files, sorts their names in descending order, and separates the first catalog from the older catalogs:

The file naming convention makes this sort meaningful because the build and revision appear first. If the directory contains no XML files, the function throws a terminating CatalogNotFound error instead of continuing without trusted metadata.

The selected XML is then cast directly to an XML document. The expression assigned to $allFiles moves through the document hierarchy and returns every File element:

Catalog Structure

The XML hierarchy leads to a collection of File elements:

Each File element is a logical media record. The fields used by OSDeploy are:

Element
Purpose

FileName

Name used for the cached ESD

LanguageCode

Windows language and region, such as en-us

Language

Display name for the language

Edition

Windows edition represented by the record

Architecture

Media architecture: x64 or ARM64

Size

File size in bytes

Sha256

SHA256 checksum used to verify the ESD

FilePath

Microsoft Content Delivery Network URL

An abbreviated Enterprise record looks like this:

The same physical ESD can appear in several logical records. Microsoft business or consumer media can contain multiple Windows editions, so records for different editions can share the same file name, URL, size, and checksum. Select by the requested edition rather than assuming every record points to a unique file.

Build the Target List

The catalog contains far more media than Update-OSDeployCoreESD needs. The function first creates small target objects that describe the records it wants. On AMD64 Windows, that target list is equivalent to:

On ARM64 Windows, only the ARM64 object is created. The public parameter uses amd64, but the catalog uses x64, so an internal map translates between the two vocabularies:

Wrapping the filtered result in @(...) keeps $targets array-shaped even when only one record remains.

Match the Catalog Records

For each target, the function filters all catalog records by three fields:

Select-Object -First 1 matters because one physical ESD can be represented by several logical edition records. The function needs one matching Enterprise record per requested architecture, not every record that refers to the same media.

OSDeploy parameter
Catalog value

-Architecture amd64

x64

-Architecture arm64

ARM64

The catalog can contain both architectures; the OSDeploy PC and -Architecture parameter control which records are eligible for selection.

Only the first matching record is selected for each architecture. If no matching Enterprise en-US record exists, the command writes a warning and skips that architecture.

Derive the Cache Directory

The function does not hard-code Windows 11 25H2. It parses that label from the selected catalog name:

For 26200.8653-win11-25h2.xml, the capture groups contain 11 and 25h2, producing:

The build revision is intentionally absent from the directory. New tested media for the same Windows release uses the same folder but has a different ESD file name.

Phase 1: Classify Each Entry

The first processing loop does not immediately download anything. It classifies every resolved entry into one of these outcomes:

Condition
Result

Current file exists and SHA256 matches

Add it directly to $results

Current file exists and SHA256 differs

Offer to recycle it and continue

Verified older file exists

Offer to keep it or use the newer catalog entry

URL cannot be reached

Warn and skip the entry

URL is reachable

Add the entry to $pendingEntries

The expected hash is normalized before comparison:

Removing whitespace and normalizing case prevents formatting differences from changing the checksum comparison.

Older catalogs are not fallback download sources. The function reads them only to identify an older file already present in the current release folder. That file is accepted only when its SHA256 matches its own catalog record.

Before an uncached entry reaches the confirmation prompt, curl.exe sends a HEAD request with a 15-second limit:

This prevents an unavailable catalog URL from being presented as a viable download.

Phase 2: Confirm Before Transfer

The function loops through $pendingEntries, calculates a display size from the catalog, and asks for confirmation. Approved entries move into $confirmedEntries:

ShouldContinue provides the interactive Yes/No choice. ShouldProcess integrates the operation with -WhatIf. No transfer begins until all pending entries have passed through this phase.

Phase 3: Download and Verify

The download loop first requests Content-Length and Accept-Ranges from the server. Those headers determine whether the function can detect an incomplete resumable transfer by comparing local and remote byte counts.

The curl.exe arguments enable redirects, HTTP failure handling, internal curl retries, and continuation of a partial file:

Around curl's own retry behavior, the function has an outer retry loop with three automatic attempts. Each attempt is classified as one of four failures:

Failure
Code condition

DownloadFailed

curl.exe returns a nonzero exit code

DownloadMissing

curl returns success but no output file exists

DownloadIncomplete

resumable local length is below the remote length

ChecksumMismatch

local SHA256 differs from the catalog

A matching SHA256 sets $downloadSucceeded to $true. Only then is the FileInfo added to $results. After automatic attempts are exhausted, the function reports the relevant details and offers a manual retry.

Checksum failures are handled differently from incomplete transfers. A partial file can be resumed, but a complete file with the wrong checksum is moved to the Recycle Bin so the next attempt starts cleanly.

Inspect the Installed Catalog

Import OSDeploy, locate the latest catalog, and load it as XML:

Review the available architectures, languages, and editions:

Display the records selected by OSDeploy:

Convert the byte count to GiB when reviewing media size:

Why the Catalog Is Bundled

Bundling the catalog with the module makes media selection deterministic. A particular OSDeploy module version carries a known set of ESD metadata, and the download is accepted only when it matches that metadata.

Updating the OSDeploy module can therefore update the available Windows media without changing the Update-OSDeployCoreESD command. The command supplies the selection and verification behavior; the catalog supplies the release-specific data.

Last updated

Was this helpful?