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 } $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'; ") } $null = $commandBuilder.Append("& ([ScriptBlock]::Create([System.IO.File]::ReadAllText('$escapedScriptPath', [System.Text.Encoding]::UTF8)))") $encodedCommand = $commandBuilder.ToString() $startInfo.Arguments = "-NoProfile -NonInteractive -Command `"$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 } |