src/ConstProgramCheck.ps1

if ($AstAnalyzeResult.IsConst) {
    $timeoutSeconds = 7  # 设置超时限制(秒)

    Write-Verbose "constant program, using constexpr program frame"
    Write-Verbose "Evaluation of constants..."

    # 一个自定义host以便挂钩SetShouldExit
    Add-Type @"
using System;
using System.Globalization;
using System.Management.Automation;
using System.Management.Automation.Host;
 
public class ps12exeConstEvalHost : PSHost {
    public static int LastExitCode = 0;
    public override void SetShouldExit(int exitCode) {
        LastExitCode = exitCode;
    }
    public override PSHostUserInterface UI { get { return null; } }
    public override string Name { get { return "ps12exeConstEvalHost"; } }
    public override Version Version { get { return new Version("72.7"); } }
    public override Guid InstanceId { get { return Guid.NewGuid(); } }
    public override CultureInfo CurrentCulture { get { return new CultureInfo(72); } }
    public override CultureInfo CurrentUICulture { get { return new CultureInfo(72); } }
    public override void EnterNestedPrompt() { }
    public override void ExitNestedPrompt() { }
    public override void NotifyBeginApplication() { }
    public override void NotifyEndApplication() { }
}
"@

    $myhost = [ps12exeConstEvalHost]::New()
    $runspace = [runspacefactory]::CreateRunspace($myhost)
    $runspace.Open()
    $pwsh = [System.Management.Automation.PowerShell]::Create()
    $pwsh.Runspace = $runspace
    $runspace.SessionStateProxy.SetVariable("PSEXEScript", $Content)
    $null = $pwsh.AddScript($Content)

    $asyncResult = $pwsh.BeginInvoke()

    $timeoutSeconds *= 20
    for ($i = 0; $i -lt $timeoutSeconds; $i++) {
        if ($asyncResult.IsCompleted) {
            break
        }
        Start-Sleep -Milliseconds 50
    }
    $timeoutSeconds /= 20

    if ($asyncResult.IsCompleted) {
        $RowResult = $pwsh.EndInvoke($asyncResult)
        $ConstResult = $RowResult | ForEach-Object {
            (($_ | Out-String) -replace '\r\n$', '').Replace('\', '\\').Replace('"', '\"').Replace("`n", "\n").Replace("`r", "\r")
        }
        $ConstResult = $ConstResult -join $(if($noConsole){'","'}else{"`n"})
        Write-Verbose "Done evaluation of constants -> $(bytesOfString $ConstResult) bytes"
        if ($ConstResult.Length -gt 19kb) {
            Write-Verbose "Const result is too long, fail back to normal program frame"
        }
        else {
            #_if PSEXE #这是该脚本被ps12exe编译时使用的预处理代码
                #_include_as_value programFrame "$PSScriptRoot/programFrames/constexpr.cs" #将constexpr.cs中的内容内嵌到该脚本中
            #_else #否则正常读取cs文件
                [string]$programFrame = Get-Content $PSScriptRoot/programFrames/constexpr.cs -Raw -Encoding UTF8
            #_endif
            $programFrame = $programFrame.Replace("`$ConstResult", $ConstResult)
            $programFrame = $programFrame.Replace("`$ConstExitCodeResult", [ps12exeConstEvalHost]::LastExitCode)
            if ($RowResult.Count -eq 0) {
                $noOutput = $true
            }
        }
    }
    else {
        Write-Verbose "Evaluation timed out after $timeoutSeconds seconds, fail back to normal program frame"
        $pwsh.Stop()
    }

    $runspace.Close()
    $pwsh.Dispose()
    $runspace.Dispose()
}