param([Parameter(Mandatory=$true)][string]$OutFile, [Parameter(Mandatory=$true)][string]$Work, [int]$HoldSeconds = 6) $lines = New-Object System.Collections.Generic.List[string] function L($s) { $lines.Add($s); [System.IO.File]::WriteAllLines($OutFile, $lines, (New-Object System.Text.UTF8Encoding($false))) } function Asm([string]$n) { return [AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq $n } | Select-Object -First 1 } L ("PSVersion: " + $PSVersionTable.PSVersion + " CLR " + [System.Environment]::Version) $isDesktop = ($PSVersionTable.PSEdition -eq 'Desktop') $fx = if ($isDesktop) { 'net461' } else { 'netstandard2.0' } L "" L "############ A) Spectre.Console on PowerShell $($PSVersionTable.PSVersion) - CJK ALIGNMENT CHECK ############" $scOk = $false try { foreach ($p in @( (Join-Path $Work "system.runtime.compilerservices.unsafe-4.5.3\lib\net461\System.Runtime.CompilerServices.Unsafe.dll"), (Join-Path $Work "system.buffers-4.5.1\lib\net461\System.Buffers.dll"), (Join-Path $Work "system.numerics.vectors-4.5.0\lib\net46\System.Numerics.Vectors.dll"), (Join-Path $Work "system.memory-4.5.5\lib\$fx\System.Memory.dll"), (Join-Path $Work "sc049\lib\netstandard2.0\Spectre.Console.dll") )) { Add-Type -Path $p -ErrorAction Stop } $ansiT = (Asm 'Spectre.Console').GetType('Spectre.Console.AnsiConsole') $tableT = (Asm 'Spectre.Console').GetType('Spectre.Console.Table') $colT = (Asm 'Spectre.Console').GetType('Spectre.Console.TableColumn') $extT = (Asm 'Spectre.Console').GetType('Spectre.Console.TableExtensions') $t = [Activator]::CreateInstance($tableT) $t.AddColumn([Activator]::CreateInstance($colT, [object[]]@('Description'))) $t.AddColumn([Activator]::CreateInstance($colT, [object[]]@('Size'))) $t.AddColumn([Activator]::CreateInstance($colT, [object[]]@('State'))) $m = $extT.GetMethod('AddRow', [Type[]]@($tableT, [string[]])) $m.Invoke($null, [object[]]@($t, [string[]]@('alpha-8c', '1.2 GB', 'OK'))) | Out-Null $m.Invoke($null, [object[]]@($t, [string[]]@('中文备份', '1.2 GB', 'OK'))) | Out-Null $m.Invoke($null, [object[]]@($t, [string[]]@('z', '1.2 GB', 'OK'))) | Out-Null $m.Invoke($null, [object[]]@($t, [string[]]@('混合 mixed 文本', '340 MB', 'WARN'))) | Out-Null Write-Host "" Write-Host (" ===== Spectre.Console 0.49.1 / PS $($PSVersionTable.PSVersion) : is the CJK row's LAST column aligned? =====") -ForegroundColor Cyan $ansiT::Write($t) Write-Host "" $ansiT::Markup('[red]red[/] [green]green[/] [yellow]yellow[/] [bold]bold[/]') Write-Host "" $scOk = $true L " Table with a 2-CJK-char row and an 8-ASCII-char row rendered. Visually compare whether the" L " 'Size' column starts at the same screen column for 'alpha-8c' (8 chars) and '中文备份' (4 chars / 8 columns)." L "RESULT-A: SpectreConsole=WORKS on PS $($PSVersionTable.PSVersion)" } catch { L (" FAILED: " + $_.Exception.GetType().Name + ': ' + $_.Exception.Message) $ie = $_.Exception.InnerException; while ($ie) { L (" inner: " + $ie.GetType().Name + ': ' + ($ie.Message -split "`n")[0]); $ie = $ie.InnerException } L "RESULT-A: SpectreConsole=FAILED" } L "" L "############ B) Terminal.Gui 1.15.0 - corrected NetMainLoop construction ############" try { Add-Type -Path (Join-Path $Work 'nstack111\lib\netstandard2.0\NStack.dll') -ErrorAction Stop Add-Type -Path (Join-Path $Work 'tg115\lib\net472\Terminal.Gui.dll') -ErrorAction Stop $tgAsm = Asm 'Terminal.Gui' $appT = $tgAsm.GetType('Terminal.Gui.Application') $drvT = $tgAsm.GetType('Terminal.Gui.NetDriver') $mlT = $tgAsm.GetType('Terminal.Gui.IMainLoopDriver') $loopT = $tgAsm.GetType('Terminal.Gui.NetMainLoop') $drv = [Activator]::CreateInstance($drvT) L (" NetDriver instance created: " + $drv.GetType().FullName) $ctor = $loopT.GetConstructors([System.Reflection.BindingFlags]'Public,NonPublic,Instance') | Select-Object -First 1 $args = @() foreach ($p in $ctor.GetParameters()) { if ($p.ParameterType.IsAssignableFrom($drv.GetType())) { $args += , $drv } elseif ($p.ParameterType -eq [bool]) { $args += , $true } else { $args += , $null } } L (" NetMainLoop ctor args: " + (($args | ForEach-Object { if ($_ -eq $null) { 'null' } else { $_.GetType().Name } }) -join ', ')) $loop = $ctor.Invoke($args) L (" NetMainLoop constructed: " + ($loop.GetType().FullName)) $initM = $appT.GetMethod('Init', [Type[]]@($drvT, $mlT)) $initM.Invoke($null, @($drv, $loop)) | Out-Null L " Application.Init(NetDriver, NetMainLoop) -> SUCCEEDED *** Terminal.Gui 1.15.0 IS LIVE on PowerShell $($PSVersionTable.PSVersion) ***" $winT = $tgAsm.GetType('Terminal.Gui.Window'); $lblT = $tgAsm.GetType('Terminal.Gui.Label'); $btnT = $tgAsm.GetType('Terminal.Gui.Button') $w = [Activator]::CreateInstance($winT, [object[]]@("BakNRet / Terminal.Gui - PowerShell $($PSVersionTable.PSVersion)")) $l1 = [Activator]::CreateInstance($lblT, [object[]]@("Terminal.Gui 1.15.0 (net472) on $(if ($isDesktop) { '.NET Framework ' } else { '.NET ' })" + [System.Environment]::Version)) $l2 = [Activator]::CreateInstance($lblT, [object[]]@('CJK cell test: 2 CJK chars -> 4 columns')) $l3 = [Activator]::CreateInstance($lblT, [object[]]@('Box drawing')) $b1 = [Activator]::CreateInstance($btnT, [object[]]@('OK')) $w.Add($l1); $w.Add($l2); $w.Add($l3); $w.Add($b1) $w.X = 1; $w.Y = 1; $w.Width = 78; $w.Height = 10 $l1.Y = 1; $l2.Y = 3; $l3.Y = 4; $b1.Y = 6; $b1.X = 2 ($appT.GetProperty('Top')).SetValue($null, $w) ($appT.GetProperty('Current')).SetValue($null, $w) $w.SetFocus(); $w.Redraw($w.Bounds) $appT.GetMethod('Refresh', [Type[]]@()).Invoke($null, @()) | Out-Null L " painted Window(78x10) + 3 Labels + Button; holding $HoldSeconds s" Start-Sleep -Seconds $HoldSeconds $appT.GetMethod('Shutdown', [Type[]]@()).Invoke($null, @()) | Out-Null L " Application.Shutdown() -> clean" L "RESULT-B: TerminalGui=WORKS on PS $($PSVersionTable.PSVersion)" } catch { L (" FAILED: " + $_.Exception.GetType().Name + ': ' + $_.Exception.Message) $ie = $_.Exception.InnerException; while ($ie) { L (" inner: " + $ie.GetType().Name + ': ' + ($ie.Message -split "`n")[0]); $ie = $ie.InnerException } L "RESULT-B: TerminalGui=FAILED" } if (-not [Console]::IsOutputRedirected) { Write-Host ""; Write-Host ("[settled PS " + $PSVersionTable.PSVersion + "] closing in $HoldSeconds s") -ForegroundColor Yellow; Start-Sleep -Seconds $HoldSeconds }