private/Get-OSDeployWindowsAdkInstall.ps1

#Requires -PSEdition Core

function Get-OSDeployWindowsAdkInstall {
    <#
    .SYNOPSIS
        Gets Windows ADK installation information
 
    .DESCRIPTION
        Reads the 32-bit Windows Kits Installed Roots registry key and verifies the
        Assessment and Deployment Kit directory. When available, it reads the installed
        product version from the machine uninstall registry, then falls back to an amd64 or
        arm64 winpe.wim, BuildLabEx, or a child registry key name. The function always returns
        one status object, including when no ADK installation is found.
 
    .EXAMPLE
        PS> Get-OSDeployWindowsAdkInstall
 
        Returns the detected ADK installation status, path, and version.
 
    .INPUTS
        None. This function does not accept pipeline input.
 
    .OUTPUTS
        System.Management.Automation.PSCustomObject. Returns one object with IsInstalled,
        InstallPath, and InstallVersion properties. InstallPath and InstallVersion can be
        null when the ADK is not detected or its version cannot be resolved.
 
    .NOTES
        Author: David Segura
        Company: Recast Software
        Version: 0.1.0
        Date: 2026-08-28
 
        Dependencies:
          PowerShell Modules: Dism when winpe.wim is available
          Windows Features: Windows registry, Windows ADK when installed
          DotNet Classes: System.Management.Automation.PSCustomObject
    #>

    [CmdletBinding()]
    param ()

    $result = [ordered]@{
        IsInstalled    = $false
        InstallPath    = $null
        InstallVersion = $null
    }

    $regPath = 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows Kits\Installed Roots'

    if (Test-Path -Path $regPath) {
        $kitsRoot = Get-ItemPropertyValue -Path $regPath -Name 'KitsRoot10' -ErrorAction SilentlyContinue
        if ($kitsRoot) {
            $adkPath = Join-Path $kitsRoot 'Assessment and Deployment Kit'
            if (Test-Path -Path $adkPath) {
                $result.IsInstalled = $true
                $result.InstallPath = $adkPath

                $adkRegistryPaths = @(
                    'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
                    'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
                )
                foreach ($adkRegistryPath in $adkRegistryPaths) {
                    $adkEntry = Get-ItemProperty -Path $adkRegistryPath -ErrorAction SilentlyContinue |
                        Where-Object {
                            $_ -and
                            $_.PSObject.Properties['DisplayName'] -and
                            $_.DisplayName -like 'Windows Assessment and Deployment Kit*' -and
                            $_.DisplayName -notlike '*Preinstallation Environment*' -and
                            $_.PSObject.Properties['DisplayVersion']
                        } |
                        Select-Object -First 1
                    if ($adkEntry) {
                        $result.InstallVersion = [string]$adkEntry.DisplayVersion
                        break
                    }
                }

                # Fall back to the WinPE image version when uninstall metadata is unavailable.
                $winpePath = Join-Path $adkPath 'Windows Preinstallation Environment'
                if (-not $result.InstallVersion -and (Test-Path $winpePath)) {
                    # Try to get version from the winpe.wim file if available
                    $wimFile = Join-Path $winpePath 'amd64\en-us\winpe.wim'
                    if (-not (Test-Path $wimFile)) {
                        $wimFile = Join-Path $winpePath 'arm64\en-us\winpe.wim'
                    }
                    if (Test-Path $wimFile) {
                        try {
                            $wimInfo = Get-WindowsImage -ImagePath $wimFile -Index 1 -ErrorAction SilentlyContinue
                            if ($wimInfo) {
                                $result.InstallVersion = "$($wimInfo.MajorVersion).$($wimInfo.MinorVersion).$($wimInfo.Build).$($wimInfo.SPBuild)"
                            }
                        }
                        catch {
                            Write-Verbose "[$($MyInvocation.MyCommand.Name)] Could not read WinPE image version: $_"
                        }
                    }
                }

                # Fallback: use the KitsRoot10 path version segment
                if (-not $result.InstallVersion) {
                    $buildLabEx = Get-ItemPropertyValue -Path $regPath -Name 'BuildLabEx' -ErrorAction SilentlyContinue
                    if ($buildLabEx) {
                        $result.InstallVersion = $buildLabEx
                    }
                    else {
                        # Use the registry key names under Installed Roots as version indicators
                        $versionKeys = Get-ChildItem -Path $regPath -ErrorAction SilentlyContinue |
                            Select-Object -ExpandProperty PSChildName |
                            Sort-Object -Descending
                        if ($versionKeys) {
                            $result.InstallVersion = $versionKeys[0]
                        }
                    }
                }
            }
        }
    }

    [PSCustomObject]$result
}