Windows?终端模拟器? 嘉豪看到要开始不懂装懂了,接入个CMD不就 OK 了?难的就是接入CMD本身。
我的目标就是实现在WinForm或者WPF下的原生渲染终端画面
一开始我也是这么认为的,拿个richtextbox或者TextBlock不就 OK 了?但是终端远不止输入输出,24 位真彩色、ANSI/VT 转义序列、鼠标支持和真实的控制台交互…
标准流重定向确实能完美跑 ping、dir,但是它跑不了真正的 PowerShell 交互模式!
当用纯代码标准重定向运行 powershell.exe 时,Windows 会发现 “哦,调用我的不是原生的黑框框控制台”。于是 Windows 不会给 PTY(伪终端)权限。
失去 PTY 意味着什么?按 Tab 键,它不会补全代码,只会输出一个傻傻的 \t 字符。按键盘的 上、下 方向键,它无法调出历史命令,只会输出 ^[
而且我发现,绝大多数第三方 Windows 终端模拟器都是用的WebView2 + xterm.js。包括曾经著名的FluentTerminal
https://github.com/felixse/FluentTerminal/blob/master/FluentTerminal.Client/src/index.ts
但是我对在桌面应用使用 web 技术是深恶痛绝的,所以当务之急是找个轮子,要好的轮子。
微软直到 Windows 10 (1809 版本),才终于在系统底层开放了真正的伪终端 API:ConPTY(CreatePseudoConsole),所以能找到用ConPTY的轮子是最好的
ConPTY的连接
这里踩的坑已经单独写过一篇文章了,所以这里提一嘴,Microsoft Terminal 项目里有示例项目教你如何使用ConPTY启动cmd并把输入输出流重定向出来
https://github.com/microsoft/terminal/tree/main/samples/ConPTY
但是注意,这里面是不包括终端渲染的,GUIConsole只是把输入输出流显示到textblock里面
用过的轮子
下面是我用过的轮子,我将告诉你我踩过坑和轮子之间的对比,然后给你推荐一个神级轮子
EasyWindowsTerminalControl
https://github.com/mitchcapper/EasyWindowsTerminalControl
这个仓库头一次点开一看不得了,nuget装上然后一句
1 |
|
就能用了,但是我在最新版本 Windows,使用.NET 10实测,窗口完全黑屏,有那个_在闪,但是没内容输出,输入也没反应,没有报错没有异常,毫无任何头绪
疑似是底层的伪控制台(ConPTY / cmd.exe)启动失败或未能成功连接数据流。
如果打开TermExample 源码,会发现那个示例项目里 MainWindow.xaml 和后台代码写了几百上千行,包含各种事件订阅、主题切换、进程拦截、TermPTY 实例的创建和绑定。
作者在设计这个库时的初衷,可能确实是想让它成为一行代码就能跑的傻瓜控件。(作者在 README 原话也是这么写的:*“In theory just add… then * <term:EasyTerminalControl StartupCommandLine="pwsh.exe" /> ”)。
但是,现实情况是它翻车了。
UI 前端渲染成功了,但背后的 cmd.exe 根本没连上,且把错误吞掉了。
懒得折腾了 换轮子
poderosa
https://github.com/poderosaproject/poderosa
上次 release 发布是在 2025 年 5 月 说明还是有在维护的。Poderosa 绝对是 .NET 终端模拟器历史上的一座丰碑,它的源码里藏着极其庞大、完整、且经过几十年考验的纯 C# VT100/Xterm 解析引擎,也就是那个能把乱码和控制序列变成带有颜色、光标位置的二维文字网格的核心。
但是要注意,Poderosa 不是一个可以随便拖拽的 DLL 控件,它是一个高度耦合的插件化框架应用。Poderosa 采用了极其古老且严密的 IoC 插件架构。它的 UI 渲染、按键拦截、网络协议全是通过接口动态注入的。
如果我要把他的终端渲染功能拿下来做成窗口组件,我要下载它的源码,找到 Poderosa.TerminalEmulator 和 Poderosa.Core 文件夹,把里面的 EscapeSequenceProcessor 和 TextBuffer 掏出来,然后自己写一个简单的重定向类把 powershell.exe 的 StandardOutput 塞给这个处理器。
vs-pty.net
https://github.com/microsoft/vs-pty.net
微软出的,Pty.Net 是一个跨平台的 .NET 库,为 .NET 提供惯用的绑定forkpty()
但是你怎么就 63 颗星星啊,怎么nuget | package not found
打开nuget进去看看 所有者已将此软件包从列表中移除。这可能意味着该软件包已弃用、存在安全漏洞或不应再使用。
forkpty 是一个 Unix/Linux 系统函数,用于创建一个伪终端(Pseudo-Terminal,简称 pty)并从中 fork 出一个子进程。它将子进程的标准输入、输出和错误都连接到这个伪终端
那还说啥了,本来也不能在 Windows 用,forkpty是 Linux/Mac 的
XtermSharp
https://github.com/migueldeicaza/XtermSharpXtermSharp 是一个用于 .NET 的 VT100/Xterm 终端模拟器,其引擎旨在与潜在的前端和后端无关。
终端本身并不负责将数据连接到进程或远程服务器。数据是通过将包含数据的字节数组传递给 “Feed” 方法发送到终端的。
这不就是我要的轮子吗?直接git clone
我操,怎么开局先卸载掉了两个项目。

先忽略掉 “此解决方案包含具有漏洞的包”,点开它的核心实现,让我看看它的源码Pty.cs
1 | [] |
这完全就是在 Mac 上面跑的。但是我觉得这个东西如果能移植到 Windows 成一个窗口控件?
说干就干,开始移植
NStack.Rune→System.Text.RuneNStack.Rune(基于 int)替换为 .NET 10 原生的System.Text.Rune,ustring(NStack 字符串)全部替换为 stringUnix Pty.cs→ WindowsConPTY完全重写
原来的Pty.cs是 macOS 专用(forkpty、libpty.dylib),Windows 下改用 Win32ConPTYAPI(CreatePseudoConsole、ResizePseudoConsole)System.Drawing.Point处理SelectionService.cs用了System.Drawing.Point,WPF 用System.Windows.Point,WinForms 保留System.Drawing.Point,Core 层用自定义结构体隔离基于
DrawingVisual+GlyphRun的做个渲染器
第一次问题,无法输入,中文无法显示。

一开始我用的 GlyphRun 方案,而它底层 API 在检测到 Consolas 字体中没有文本包含的该汉字轮廓时,就会直接把它抛弃。
把这个地方的逻辑切换回 FormattedText。这样能显示了
还有在初始加载时没有自动获取 WPF 窗口的焦点树。要在鼠标点击事件中补充了强制对齐获取焦点的代码:Focus()。
然后中文正常显示,也能输入东西了

OK 勉强能用了,但是所有快捷键都是失效的 (包括F1~F12,和类似ctrl+x的组合键)。还有,回车会触发两次,按了一次回车会有按了两次的效果。
还有按backspace的时候,如果没有连上SSH linux,就会按一次backspace会往前一直删到有空格才停下,如果在ssh会话里面就是会按两次 (也不一定)。
还有鼠标点击也是失效的。还有中文适配也有问题。
还有就是现在不支持彩色输出.
组合键和功能键失效、回车 / 退格双击问题,WPF/Winforms 默认触发的是原始文本输入 (如 \r),所以需要重写整个 KeyDown 的字典树翻译器
让它完全拦截所有的 F1-F12、方向键、PageUp/Down、Insert/Delete 以及 Ctrl + A-Z 的组合键,而且将它们原生翻译为真正的 VT100 ANSI 字节控制码输入管道中。
彩色输出问题,利用移位操作提取出前景色、背景色以及加粗 / 斜体 / 反色的 Flag,这样能显示彩色了。

但是这个中文间距依旧飞来飞去,那个小白块想在哪闪就在哪闪

像htop这种的有复杂点的TUI的,鼠标能点的地方点击无反应,而且TUI非常莫名就容易乱。
与此同时我的 claude 还被干限额了,,直接回归古法编程。
这里你看我这么说遇到的 bug,解决 bug 可能觉得很轻松,但是实际难度,你真上手体验就知道了。
放弃了 这东西本来就是给 MAC 写的 我就还是不去逆天而行了
如果你有意接力它的适配,点击下面链接下载我到这一步的移植源代码
https://www.cloudyou.top/files/XtermSharp_win.zip
如果你觉得我修复上面几个 bug 很轻松的话。来,你来下载源码,修复TUI渲染和中文还有鼠标点击,那这个轮子将不逊色于下面这个轮子
绝佳轮子

我无意发现 Windows Terminal不是纯C实现啊,有C#的代码 难道说

没错,踏破铁鞋无觅处,得来全不费功夫,我一开始在寻找的窗口控件,微软早就写好了。
OK,把项目git clone下来,用 VS 打开,把所有项目全部重定向到当前已经安装的生成工具和 SDK。
先跑一遍编译,但还是有报错需要v143工具集,但是我电脑只有v145工具集。还有几个项目 vs 没有给我重定向
解决方法也简单,用 vscode 或者别的编辑器而不是 IDE 打开项目,全局搜索替换v143到v145,然后就能编译了
注意编译过程,虚拟内存要设置大于 20G,不然会编译失败
先打开powershell按照文档跑一遍全部编译
1 | Import-Module .\tools\OpenConsole.psm1 |
然后 vs 打开 Terminal 下面的 wpf 下面的WpfTerminalTestNetCore,需要的Microsoft.Terminal.Control.dll应该能右键在资源管理器里面显示了
直接生成运行WpfTerminalTestNetCore

成了!渲染效果和 Windows Terminal 是一样的
让我们把它接入cmd的ConPTY,先做个ConPtyConnection类
1 | using Microsoft.Terminal.Wpf; |
然后在WPF中引用它
1 | <Window x:Class="WpfTerminalTestNetCore.CmdWindow" |
然后在窗口代码里使用它
1 | private ConPtyConnection _connection; |

编译出来运行,这期神了,中文显示,快捷键/组合键,复杂TUI,窗口大小改变重绘,鼠标点击,该有的功能一个都不落,这才是Windows终端模拟器的最佳解决方案
毕竟它接的就是Windows Terminal,Windows Terminal有的功能他都有