private/MDT/Get-MDTWindowsAdkPaths.ps1

function Get-MDTWindowsAdkPaths {
    <#
    .SYNOPSIS
        Retrieves command paths for the Windows Assessment and Deployment Kit (ADK).
 
    .DESCRIPTION
        Resolves the Windows ADK root from the registry
        (HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows Kits\Installed Roots,
        value KitsRoot10) or falls back to the default install location at
        '%ProgramFiles(x86)%\Windows Kits\10'. Builds and returns a
        PSCustomObject containing the full paths to ADK tools such as
        dism.exe, imagex.exe, oscdimg.exe, oa3tool.exe, and the WinPE root.
 
    .PARAMETER Architecture
        Target processor architecture passed to ADK path resolution.
        Default: 'amd64'.
 
    .PARAMETER WindowsAdkRoot
        Explicit path to the Windows ADK root directory. If not supplied,
        the path is resolved from the registry or the default install location.
 
    .EXAMPLE
        Get-MDTWindowsAdkPaths
 
        Returns a PSCustomObject containing all ADK tool paths for the amd64
        architecture using the registry-resolved ADK installation.
 
    .EXAMPLE
        $adkPaths = Get-MDTWindowsAdkPaths -Architecture 'amd64'
        $adkPaths.oscdimgexe
 
        Returns the full path to oscdimg.exe for the amd64 architecture.
 
    .INPUTS
        None. This function does not accept pipeline input.
 
    .OUTPUTS
        System.Management.Automation.PSCustomObject
        An object with properties for each resolved ADK tool path.
 
    .NOTES
        Author: David Segura
        Company: Recast Software
    #>

    [CmdletBinding()]
    param (
        [Parameter()]
        [string]$Architecture = 'amd64',

        [Parameter()]
        [Alias('AdkRoot')]
        [string]$WindowsAdkRoot
    )
    #=================================================
    Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand)] Start"
    $Error.Clear()
    #=================================================
    # region Get Windows ADK information from the Registry
    $DefaultPath = "${env:ProgramFiles(x86)}\Windows Kits\10"
    $InstalledRoots32 = 'HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots'
    $InstalledRoots64 = 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows Kits\Installed Roots'
    $RegistryValue = 'KitsRoot10'
    $KitsRoot10 = $null

    if (Test-Path -Path $InstalledRoots64) {
        $RegistryKey = Get-Item -Path $InstalledRoots64
        if ($null -ne $RegistryKey.GetValue($RegistryValue)) {
            $KitsRoot10 = Get-ItemPropertyValue -Path $InstalledRoots64 -Name $RegistryValue -ErrorAction SilentlyContinue

            if (Test-Path -Path $KitsRoot10) {
                Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand)] Found KitsRoot10 in $InstalledRoots64"
            }
            else {
                Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand)] KitsRoot10 path from registry does not exist: $KitsRoot10"
                $KitsRoot10 = $null
            }
        }
        else {
            Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand)] Registry value $RegistryValue not found in $InstalledRoots64"
        }
    }

    if (-NOT ($KitsRoot10)) {
        if (Test-Path -Path $DefaultPath) {
            Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand)] Found KitsRoot10 in $DefaultPath"
            $KitsRoot10 = $DefaultPath
        }
    }

    if (-NOT ($KitsRoot10)) {
        if (Test-Path -Path $InstalledRoots32) {
            $RegistryKey = Get-Item -Path $InstalledRoots32
            if ($null -ne $RegistryKey.GetValue($RegistryValue)) {
                $KitsRoot10 = Get-ItemPropertyValue -Path $InstalledRoots32 -Name $RegistryValue -ErrorAction SilentlyContinue
            }
            else {
                Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand)] Registry value $RegistryValue not found in $InstalledRoots32"
            }
        }
    }

    Write-Verbose "[$(Get-Date -format s)] [$($MyInvocation.MyCommand)] $KitsRoot10"

    if ($KitsRoot10) {
        $WindowsAdkRoot = Join-Path $KitsRoot10 'Assessment and Deployment Kit'
    }
    else {
        Write-Warning "[$(Get-Date -format s)] [$($MyInvocation.MyCommand)] Unable to determine ADK Path"
        return
    }
    #endregion
    #=================================================
    # region Validate Windows ADK Path
    $WinPERoot = Join-Path $WindowsAdkRoot 'Windows Preinstallation Environment'
    if (-NOT (Test-Path $WinPERoot -PathType Container)) {
        Write-Warning "[$(Get-Date -format s)] WinPERoot is not a valid path $WinPERoot"
        $WinPERoot = $null
        return
    }
    #endregion
    #=================================================
    # region Set ADK Paths
    $PathDeploymentTools = Join-Path $WindowsAdkRoot (Join-Path 'Deployment Tools' $Architecture)
    $PathWinPE = Join-Path $WinPERoot $Architecture
    #endregion
    #=================================================
    # region Build Results
    $Results = [PSCustomObject] @{
        #KitsRoot = $KitsRoot10
        AdkRoot             = $WindowsAdkRoot
        PathBCDBoot         = Join-Path $PathDeploymentTools 'BCDBoot'
        PathDeploymentTools = $PathDeploymentTools
        PathDISM            = Join-Path $PathDeploymentTools 'DISM'
        PathOscdimg         = Join-Path $PathDeploymentTools 'Oscdimg'
        PathUsmt            = Join-Path $WindowsAdkRoot (Join-Path 'User State Migration Tool' $Architecture)
        PathWinPE           = Join-Path $WinPERoot $Architecture
        PathWinPEMedia      = Join-Path $PathWinPE 'Media'
        PathWinSetup        = Join-Path $WindowsAdkRoot (Join-Path 'Windows Setup' $Architecture)
        WinPEOCs            = Join-Path $PathWinPE 'WinPE_OCs'
        WinPERoot           = $WinPERoot
        WimSourcePath       = Join-Path $PathWinPE 'en-us\winpe.wim'

        bcdbootexe          = Join-Path $PathDeploymentTools (Join-Path 'BCDBoot' 'bcdboot.exe')
        bcdeditexe          = Join-Path $PathDeploymentTools (Join-Path 'BCDBoot' 'bcdedit.exe')
        bootsectexe         = Join-Path $PathDeploymentTools (Join-Path 'BCDBoot' 'bootsect.exe')
        dismexe             = Join-Path $PathDeploymentTools (Join-Path 'DISM' 'dism.exe')
        efisysbin           = Join-Path $PathDeploymentTools (Join-Path 'Oscdimg' 'efisys.bin')
        efisysnopromptbin   = Join-Path $PathDeploymentTools (Join-Path 'Oscdimg' 'efisys_noprompt.bin')
        etfsbootcom         = if ($Architecture -eq 'arm64') {
            # ARM64 does not have a etfsboot.com | Redirect to amd64 folder
            Join-Path (Join-Path $WindowsAdkRoot (Join-Path 'Deployment Tools' 'amd64')) (Join-Path 'Oscdimg' 'etfsboot.com')
        }
        else {
            Join-Path $PathDeploymentTools (Join-Path 'Oscdimg' 'etfsboot.com')
        }
        imagexexe           = Join-Path $PathDeploymentTools (Join-Path 'DISM' 'imagex.exe')
        oa3toolexe          = Join-Path $PathDeploymentTools (Join-Path 'Licensing\OA30' 'oa3tool.exe')
        oscdimgexe          = Join-Path $PathDeploymentTools (Join-Path 'Oscdimg' 'oscdimg.exe')
        pkgmgrexe           = Join-Path $PathDeploymentTools (Join-Path 'DISM' 'pkgmgr.exe')
    }
    return $Results
    #endregion
}