private/Step-BuildBootSetEnvironmentVariables.ps1

#Requires -PSEdition Core

function Step-BuildBootSetEnvironmentVariables {
    <#
    .SYNOPSIS
        Sets configured and identity environment variables in the mounted WinPE image
 
    .DESCRIPTION
        Builds an environment-variable table from global
        OSDeployModule.BootImage.env, the installed OSDeploy module version, generated
        OSDeploy identifiers, and available license email and license GUID values. The
        device UUID is SHA-256 hashed for ID_OSDEPLOYDEVICE; a generated GUID is used when the
        hash is empty. A new ID_OSDEPLOYBOOT is generated on every invocation.
 
        The function loads the mounted SYSTEM hive, creates the environment registry
        key when needed, writes each value as REG_SZ, appends X:\WinPEStartup\assets to
        the system Path as REG_EXPAND_SZ, and unloads the hive in a finally block. A
        missing SYSTEM hive produces a warning.
 
    .EXAMPLE
        PS> Step-BuildBootSetEnvironmentVariables
 
        Writes configured, version, device, and available license values into WinPE.
 
    .INPUTS
        None. This function does not accept pipeline input.
 
    .OUTPUTS
        None.
 
    .NOTES
        Author: David Segura
        Company: Recast Software
        Version: 0.1.0
        Date: 2026-08-28
 
        Requires global BuildMedia.MountPath, global OSDeployModule.BootImage.env,
        Get-OSDeployModuleVersion, Get-CimInstance, reg.exe, and access to load the
        mounted SYSTEM hive. Reads OSDCoreLicense from the caller's scope when present
        and modifies the mounted environment registry key, including the system Path.
    #>

    [CmdletBinding()]
    param ()

    $MountPath = $global:BuildMedia.MountPath

    # Build the env var table: static entries from module.json + dynamic OSDEPLOY_VERSION
    $envVars = [ordered]@{}

    $envConfig = $global:OSDeployModule.BootImage.env
    if ($envConfig) {
        foreach ($prop in $envConfig.PSObject.Properties) {
            $envVars[$prop.Name] = $prop.Value
        }
    }

    $moduleVersion = Get-OSDeployModuleVersion
    if ($moduleVersion) {
        $envVars['OSDEPLOY_VERSION'] = $moduleVersion.ToString()
    }

    # Unique identifier for this device, used for telemetry and license enforcement
    $deviceUUID = (Get-CimInstance -ClassName Win32_ComputerSystemProduct).UUID
    # Convert the UUID to a hash value to protect user privacyand ensure a consistent identifier across events
    $deviceUUIDHash = [System.BitConverter]::ToString([System.Security.Cryptography.SHA256]::Create().ComputeHash([System.Text.Encoding]::UTF8.GetBytes($deviceUUID))).Replace("-", "")
    if (-not [string]::IsNullOrWhiteSpace($deviceUUIDHash)) {
        [string]$distinctId = $deviceUUIDHash
    }
    else {
        [string]$distinctId = [System.Guid]::NewGuid().ToString()
    }

    $envVars['ID_OSDEPLOYDEVICE'] = $distinctId
    $envVars['ID_OSDEPLOYBOOT'] = $global:BuildMedia.BootGuid
    if ($OSDCoreLicense.License.Email) {
        $envVars['ID_REGISTEREDEMAIL'] = $OSDCoreLicense.License.Email
    }
    if ($OSDCoreLicense.License.LicenseGuid) {
        $envVars['ID_REGISTEREDLICENSE'] = $OSDCoreLicense.License.LicenseGuid
    }

    if ($envVars.Count -eq 0) {
        Write-HostDateTimeDarkGray 'No environment variables to set in WinPE — skipping'
        return
    }

    Write-HostDateTimeDarkGray 'Setting environment variables in WinPE SYSTEM hive'

    $systemHivePath = Join-Path $MountPath 'Windows\System32\Config\SYSTEM'
    if (-not (Test-Path $systemHivePath)) {
        Write-Warning "[$(Get-Date -Format s)] SYSTEM hive not found at $systemHivePath"
        return
    }
    #=================================================
    # Add X:\WinPEStartup\assets PATH to WinPE
    & reg LOAD HKLM\Mount "$MountPath\Windows\System32\Config\SYSTEM"
    Start-Sleep -Seconds 3
    $RegistryKey = 'HKLM:\Mount\ControlSet001\Control\Session Manager\Environment'

    $CurrentPath = (Get-Item -path $RegistryKey ).GetValue('Path', '', 'DoNotExpandEnvironmentNames')
    $NewPath = $CurrentPath + ';X:\WinPEStartup\assets'
    $Result = New-ItemProperty -Path $RegistryKey -Name 'Path' -PropertyType ExpandString -Value $NewPath -Force

    Get-Variable Result | Remove-Variable
    Get-Variable RegistryKey | Remove-Variable
    [gc]::collect()
    Start-Sleep -Seconds 3
    & reg UNLOAD HKLM\Mount
}