Private/Invoke-ColorScriptProcess.ps1

function Invoke-ColorScriptProcess {
    <#
    .SYNOPSIS
        Executes a colorscript and captures its output using an isolated process
        to preserve ANSI sequences and console rendering fidelity.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$ScriptPath,

        [switch]$ForCache
    )

    $scriptName = [System.IO.Path]::GetFileNameWithoutExtension($ScriptPath)

    $result = [pscustomobject]@{
        ScriptName = $scriptName
        StdOut     = ''
        StdErr     = ''
        ExitCode   = $null
        Success    = $false
    }

    if (-not (Test-Path -LiteralPath $ScriptPath)) {
        $result.StdErr = $script:Messages.ScriptPathNotFound
        return $result
    }

    if (-not $ForCache) {
        $staticOutput = Get-StaticColorScriptOutput -ScriptPath $ScriptPath
        if ($staticOutput.Available) {
            $result.StdOut = $staticOutput.Content
            $result.ExitCode = 0
            $result.Success = $true
            return $result
        }
    }

    $executable = Get-PowerShellExecutable
    $scriptDirectory = [System.IO.Path]::GetDirectoryName($ScriptPath)
    $process = $null

    try {
        $startInfo = New-Object System.Diagnostics.ProcessStartInfo
        $startInfo.FileName = $executable

        $escapedScriptPath = $ScriptPath.Replace("'", "''")
        $escapedScriptDir = if ($scriptDirectory) { $scriptDirectory.Replace("'", "''") } else { $null }
        $commandBuilder = New-Object System.Text.StringBuilder
        $null = $commandBuilder.Append("[Console]::OutputEncoding = [System.Text.Encoding]::UTF8; ")
        if ($escapedScriptDir) {
            $null = $commandBuilder.Append("Set-Location -LiteralPath '$escapedScriptDir'; ")
        }

        # ConsoleHost spends most of the runtime parsing thousands of ANSI sequences emitted by
        # Write-Host, only to strip them because stdout is redirected. Shadow Write-Host inside the
        # isolated child process, preserve its plain-text and -NoNewline semantics, and normalize
        # ANSI once after the script completes. The script remains process-isolated.
        $null = $commandBuilder.Append(@'
$__cseOutputBuilder = [System.Text.StringBuilder]::new();
function Write-Host {
    param(
        [Parameter(Position = 0, ValueFromPipeline, ValueFromRemainingArguments)]
        [object[]]$Object,
        [object]$Separator = ' ',
        [switch]$NoNewline,
        [System.ConsoleColor]$ForegroundColor,
        [System.ConsoleColor]$BackgroundColor
    )
    process {
        $null = $ForegroundColor, $BackgroundColor;
        $__cseText = if ($null -eq $Object) { '' } else { [string]::Join([string]$Separator, $Object) };
        $null = $__cseOutputBuilder.Append($__cseText);
        if (-not $NoNewline) { $null = $__cseOutputBuilder.Append([Environment]::NewLine) };
    }
};
'@
)
        $null = $commandBuilder.Append("`$__csePipelineOutput = & ([ScriptBlock]::Create([System.IO.File]::ReadAllText('$escapedScriptPath', [System.Text.Encoding]::UTF8))); ")
        $null = $commandBuilder.Append(@'
foreach ($__cseItem in $__csePipelineOutput) { $null = $__cseOutputBuilder.AppendLine([string]$__cseItem) };
$__cseAnsiPattern = ([string][char]27) + '\[[0-9;]*[A-Za-z]';
[Console]::Out.Write([System.Text.RegularExpressions.Regex]::Replace($__cseOutputBuilder.ToString(), $__cseAnsiPattern, ''));
'@
)

        $commandText = $commandBuilder.ToString()
        $commandBytes = [System.Text.Encoding]::Unicode.GetBytes($commandText)
        $encodedCommand = [Convert]::ToBase64String($commandBytes)
        $startInfo.Arguments = "-NoLogo -NoProfile -NonInteractive -EncodedCommand $encodedCommand"
        $startInfo.UseShellExecute = $false
        $startInfo.RedirectStandardOutput = $true
        $startInfo.RedirectStandardError = $true
        $startInfo.StandardOutputEncoding = [System.Text.Encoding]::UTF8
        $startInfo.StandardErrorEncoding = [System.Text.Encoding]::UTF8

        if ($ForCache) {
            try {
                $startInfo.EnvironmentVariables['COLOR_SCRIPTS_ENHANCED_CACHE_BUILD'] = '1'
            }
            catch {
                Write-Verbose ("Unable to set cache build environment variable: {0}" -f $_.Exception.Message)
            }
        }

        if ($scriptDirectory) {
            $startInfo.WorkingDirectory = $scriptDirectory
        }

        $process = New-Object System.Diagnostics.Process
        $process.StartInfo = $startInfo
        $null = $process.Start()

        $output = $process.StandardOutput.ReadToEnd()
        $errorOutput = $process.StandardError.ReadToEnd()
        $process.WaitForExit()

        $result.ExitCode = $process.ExitCode
        $result.StdOut = $output
        $result.StdErr = $errorOutput
        $result.Success = ($process.ExitCode -eq 0)
    }
    catch {
        $result.StdErr = $_.Exception.Message
    }
    finally {
        if ($process) {
            $process.Dispose()
        }
    }

    return $result
}