# TUI 用零依赖自研,不引入任何 TUI 库 三个候选库**全部实测排除**(不是偏好,是硬障碍): - **`Microsoft.PowerShell.ConsoleGuiTools`(`Out-ConsoleGridView`)**:PSGallery 元数据声明 `PowerShellVersion = 7.2`,**5.1 装不上**。 - **`Spectre.Console` 0.49.1(netstandard2.0)**:能在 5.1 上加载并渲染,但必须往仓库塞 **4 个第三方 DLL**(`System.Memory` / `System.Runtime.CompilerServices.Unsafe` / `System.Buffers` / `System.Numerics.Vectors`)——直接违反 README 的"运行备份/恢复不需要任何 模块"承诺。而且它**不支持鼠标**。(最新稳定版 0.57.2 还要多两个依赖,所以连版本都得钉在 0.49.1。) - **`Terminal.Gui` 1.15.0(net472)**:反射接线后 `Window` + `Label` + `Button` 在 5.1 与 7 上 **真的渲染出来了**,但 `Application.Init()` 在这个版本没有无参重载,`NetMainLoop` 是 `internal`, 且 **`Application.Shutdown()` 在两端都抛 `NullReferenceException`** —— 不能用于生产。 所以自研,只用四样东西:`$Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')`、 `[Console]::SetCursorPosition`、`Write-Host -ForegroundColor`、自算的 `Get-CellWidth`。 零依赖承诺因此保住;代价是**不支持鼠标、不做复杂控件**。 ## 两条必须记住、都实测过的坑 **一、无控制台时 `$Host.UI.SupportsVirtualTerminal` 会撒谎。** 它返回 `True`,而同一时刻 `GetConsoleMode` 已经因句柄无效而失败;`[Console]::SetCursorPosition` / `WindowWidth` / `KeyAvailable` 全部抛异常;`$Host.UI.RawUI.WindowSize` 不抛错但**静默返回假的 `160x40`**。所以: - 唯一可靠的第一道闸门是 **`[Console]::IsOutputRedirected`**,不是那个属性; - **TUI 的异常绝不改退出码** —— 退出码只属于 `$failed` 语义(计划任务靠它判断成败)。 **二、中文列宽必须自己算。** `.Length` 是 UTF-16 code unit(中文 1 个 char、2 列);而 5.1 的 `$Host.UI.RawUI.LengthInBufferCells('中文')` 返回 **2**(把中文当单列)、对边框字符返回 **6**(把 制表符当宽字符)——**5.1 上绝对不能拿它排版**,7 上它是对的,所以这个坑只在一边出现、更危险。 自建的 East-Asian-Wide 表必须覆盖全角拉丁、半角片假名(后者是 1 列)、emoji(代理对)。 另注:VT 在本机**默认已启用**(新 conhost 与 Windows Terminal 的 `STDOUT mode` 都是 `0x7`), 所以彩色与光标定位不需要 `SetConsoleMode`;但代码里保留"无 VT 时退化"的分支以防老环境。