七亿批量远程管理工具(RdpManager)发布了 v1.6.3。这次更新不大,四个修复都集中在 SSH 终端上。但这四个问题不是拍脑袋改的——都是自己用的时候撞到的,改的过程也来回折腾了几轮。写下来当个记录。
一、SSH 输出里的「口口口」方块
现象:在 SSH 终端里跑 mkfs.ext4(格式化磁盘),进度行后面跟了一串方块:
Discarding device blocks: 4096/20971264 □□□□□□□□ done
第一反应是编码问题或者字体缺字。查了一下原始字节流——全是正常的 ASCII,控制字符只有 \b(退格符 0x08)、\n、\t,没有任何乱码字节。
根因是 mke2fs 这类命令行工具做进度动画的方式:写文字 → 退格符回到行首 → 覆盖重画。RichTextBox 不认识退格符,直接渲染成了方块。
修法:在文本输出到控件前加一层退格折叠处理,按终端语义把「写内容 + 退格 + 覆盖」还原成最终可见文本。Discarding device blocks: 4096/...\b\b\b...done → Discarding device blocks: done。
CollapseBackspaces 这个函数不长,但不写单元测试纯靠猜肯定翻车——我用真实服务器的原始字节流喂进去跑了一遍才敢合入。
二、清屏后提示符不见了
点「清屏」按钮后屏幕干干净净,连 [root@www ~]# 也没了。你得等服务器再发一次才看到提示符,中间那几秒很别扭。
原来的清屏是直接 _term.Clear() 把整块文本全清了。改法:清屏时取保护区最后一行(就是提示符那行)和输入区草稿,清完后把提示符写回并标记为只读保护区,再把草稿接在后面。
顺便加了个 Ctrl+L 快捷键,跟 Xshell 习惯对齐。
三、鼠标拖选复制——改了三轮
这个最折腾。
最初的问题:SSH 终端里想复制某行输出(比如装完宝塔面板出来的地址),拖选只能从最末尾开始往上拉,永远选不中单独一行。
查代码发现之前在 MouseDown 里做了「按在输出区就把光标弹到输入行末尾」的逻辑——本意是防止用户不小心点到输出区,但副作用是拖选的锚点永远在文件末,拉选区 = 从末尾到某处全选。
第一轮:加鼠标干预保护。加了一个 _mouseSelecting 标志,拖选期间 SelectionChanged 不做归位。同时加了个双击选中整行的功能。老大试了说:不要双击选行,按住左键拖才是大众操作。删掉。
第二轮:全部交回原生。把 MouseDown、MouseUp、SelectionChanged 三个自定义事件全删了,鼠标选择完全交给 RichTextBox 原生处理。老大试了说拖选 OK 了,但 Ctrl+C 好像没反应。
排查发现 EnsureCaretEditable() 每次按键都跑——不管你有没有选中的文字,只要光标在保护区就清选区、挪到输入行末尾。所以选完文字一按 Ctrl+C,Ctrl+C 确实复制了,但选区立刻被清掉,看起来就像没复制。
第三轮:守住选区。在 EnsureCaretEditable() 开头加了一行:
if (_term.SelectionLength > 0) return;有选区就跳过,不动它。就这样一行代码的事,前面绕了两轮。
教训:终端控件里「点击归位」这类自定义逻辑天生跟鼠标拖选冲突。想让它俩共存,最稳妥的做法是只在真正需要的时候介入(打字的时候),其他时候把控制权交还给原生控件。
四、最小化主窗口,SSH 断了
开了 SSH 终端后想最小化主程序腾桌面,但一点最小化主窗口就消失了(被自动藏到了托盘),SSH 连接也跟着断了。
根因两处:
- 主窗口的 Resize 事件里判断
WindowState == Minimized就调HideToTray(),最小化按钮没法正常缩到任务栏 - SSH/SFTP/FTP 窗口是用
.Show(this)打开的,它们是主窗口的「附属窗口」。主窗口隐藏/缩走,附属窗口也跟着缩,连接就断了
修法:删掉 Resize 里的 HideToTray 调用,让最小化按钮正常缩到任务栏。SSH/SFTP/FTP 改成 .Show()(独立窗口),不附属主窗口。
五、发版踩的坑——version.json 写坏了
发新版要改官网的版本文件 version.json,客户端检查更新靠它。改完打包上传后试了一下——本地编译的程序检查更新报「检查失败,请检查网络连接」。
查了半天发现 version.json 尾部多了一截 ]}:
{"version":"1.6.3","note":"...修复..."}]}是我编辑时手抖带进去的。JSON 解析器看到 ]} 直接抛 JsonException,程序走 catch 段弹出「检查失败」。
修法很简单:重新写一遍正确的 JSON。但这个坑是在发布流程里踩的,以后发版的 checklist 上应该加一条「验证 version.json 语法」。
总结
这次 v1.6.3 没有大功能,四个修正在代码层面改动都不大——最短的就一行。但每个问题的重现、定位、验证都花了时间,尤其是拖选复制那个改了三次才做对。
很多运维工具的痛点是:功能能用,但细节磨人。这几个问题就是平时用着「有点别扭但不致命」的那种——真修好了才发现原来难受了那么久。
v1.6.3 更新日志:
- 修复 SSH 终端输出中进度条退格字符显示为方块的问题
- 清屏后保留当前命令行提示符
[root@www ~]#,支持 Ctrl+L - 优化 SSH 终端复制:按住鼠标拖选 1 行或多行,Ctrl+C / 右键复制均可用
- 优化主窗口最小化逻辑:SSH/SFTP/FTP 窗口独立于主窗口,最小化不中断连接
评论