private/Step-BuildBootCoreWinPEScript.ps1

#Requires -PSEdition Core

function Step-BuildBootCoreWinPEScript {
    <#
    .SYNOPSIS
        Runs configured and profile-local WinPE build scripts
 
    .DESCRIPTION
        Runs script paths from global BuildMedia.WinPEScript, followed by PowerShell
        scripts discovered in the build profile's boot-winpescript directory and
        its immediate subdirectories. Paths are processed in configured-first order,
        and duplicate paths are run only once. Missing paths produce warnings.
 
        Each script runs in the caller's session and can modify build state and the
        mounted image. Success-stream output from invoked scripts is passed through.
 
    .EXAMPLE
        PS> Step-BuildBootCoreWinPEScript
 
        Runs the configured and profile-local WinPE build scripts.
 
    .INPUTS
        None. This function does not accept pipeline input.
 
    .OUTPUTS
        System.Object. Passes through success-stream output produced by each invoked script.
 
    .NOTES
        Author: David Segura
        Company: Recast Software
        Version: 0.1.0
        Date: 2026-08-28
 
        Requires global BuildMedia with WinPEScript and BuildProfile properties.
        BuildProfileContentPath optionally overrides the profile-local content directory.
    #>

    [CmdletBinding()]
    param ()

    # Start with scripts explicitly configured in osdeployboot.json.
    $WinPEScript = @($global:BuildMedia.WinPEScript | Where-Object { $_ })
    $BuildProfilePath = $global:BuildMedia.BuildProfile
    $BuildProfileContentPath = $global:BuildMedia.BuildProfileContentPath
    if (-not $BuildProfileContentPath -and $BuildProfilePath) {
        $BuildProfileContentPath = Split-Path -Path $BuildProfilePath -Parent
    }
    $ProfileScriptPath = if ($BuildProfileContentPath) {
        Join-Path $BuildProfileContentPath 'boot-winpescript'
    }

    # Append profile-local scripts from boot-winpescript and its immediate subdirectories.
    if ($ProfileScriptPath -and (Test-Path -LiteralPath $ProfileScriptPath -PathType Container)) {
        $WinPEScript += Get-ChildItem -LiteralPath $ProfileScriptPath -Filter '*.ps1' -File -Recurse -Depth 1 -ErrorAction SilentlyContinue |
            Sort-Object FullName |
            Select-Object -ExpandProperty FullName
    }

    # Preserve execution order while preventing the same path from running more than once.
    $SeenScripts = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase)
    $WinPEScript = @($WinPEScript | Where-Object { $SeenScripts.Add([System.String]$_) })

    # Run each available script and warn when a configured path no longer exists.
    foreach ($Item in $WinPEScript) {
        if (Test-Path -LiteralPath $Item -PathType Leaf) {
            Write-Host -ForegroundColor DarkGray "[$(Get-Date -format s)] [INFO] boot-winpescript: $Item"
            & "$Item"
        }
        else {
            Write-Warning "[$(Get-Date -Format s)] BootImage Script not found: $Item"
        }
    }
}