如何将PowerShell输出中的ANSI格式转换为RTF/UTF-8格式?
解析ANSI颜色转义码并在RichTextBox中渲染
移除ANSI码会丢失原有格式,我们可以解析这些转义序列,将其转换为RichTextBox支持的文本样式。以下是一个直接操作RichTextBox的实现方案,无需预先转换成RTF字符串:
using System; using System.Text.RegularExpressions; using System.Windows.Forms; public static class AnsiRichTextBoxHelper { // 匹配ANSI转义序列,分组捕获SGR参数列表 private static readonly Regex AnsiEscapeRegex = new Regex(@"\x1B\[([0-9;]*)([a-zA-Z])"); // 将ANSI颜色码映射到System.Drawing.Color private static System.Drawing.Color GetAnsiColor(int code, bool isBackground) { int baseCode = isBackground ? 40 : 30; int brightOffset = isBackground ? 100 : 90; if (code >= baseCode && code < baseCode + 8) { return code switch { 30 or 40 => System.Drawing.Color.Black, 31 or 41 => System.Drawing.Color.Red, 32 or 42 => System.Drawing.Color.Green, 33 or 43 => System.Drawing.Color.Yellow, 34 or 44 => System.Drawing.Color.Blue, 35 or 45 => System.Drawing.Color.Magenta, 36 or 46 => System.Drawing.Color.Cyan, 37 or 47 => System.Drawing.Color.White, _ => System.Drawing.Color.Black }; } else if (code >= brightOffset && code < brightOffset + 8) { return code switch { 90 or 100 => System.Drawing.Color.Gray, 91 or 101 => System.Drawing.Color.DarkRed, 92 or 102 => System.Drawing.Color.Lime, 93 or 103 => System.Drawing.Color.Gold, 94 or 104 => System.Drawing.Color.DarkBlue, 95 or 105 => System.Drawing.Color.DarkMagenta, 96 or 106 => System.Drawing.Color.Turquoise, 97 or 107 => System.Drawing.Color.Snow, _ => System.Drawing.Color.White }; } return isBackground ? System.Drawing.Color.Transparent : System.Drawing.Color.Black; } public static void AppendAnsiText(this RichTextBox rtb, string ansiText) { if (rtb.InvokeRequired) { rtb.Invoke(new Action(() => AppendAnsiText(rtb, ansiText))); return; } // 保存控件初始样式 var originalForeColor = rtb.ForeColor; var originalBackColor = rtb.BackColor; var originalFont = rtb.Font; // 跟踪当前文本样式状态 bool isBold = false; bool isUnderline = false; System.Drawing.Color currentForeColor = originalForeColor; System.Drawing.Color currentBackColor = originalBackColor; int lastIndex = 0; foreach (Match match in AnsiEscapeRegex.Matches(ansiText)) { // 插入转义码之前的普通文本 if (match.Index > lastIndex) { string plainText = ansiText.Substring(lastIndex, match.Index - lastIndex); rtb.SelectionStart = rtb.TextLength; rtb.SelectionLength = 0; // 应用当前样式 rtb.SelectionColor = currentForeColor; rtb.SelectionBackColor = currentBackColor; rtb.SelectionFont = new System.Drawing.Font(originalFont, isBold ? System.Drawing.FontStyle.Bold : isUnderline ? System.Drawing.FontStyle.Underline : System.Drawing.FontStyle.Regular); rtb.SelectedText = plainText; } // 处理SGR格式序列(仅针对以m结尾的转义码) if (match.Groups[2].Value == "m") { string[] parameters = match.Groups[1].Value.Split(';', StringSplitOptions.RemoveEmptyEntries); foreach (string paramStr in parameters) { if (int.TryParse(paramStr, out int param)) { switch (param) { case 0: // 重置所有样式 isBold = false; isUnderline = false; currentForeColor = originalForeColor; currentBackColor = originalBackColor; break; case 1: // 启用粗体 isBold = true; break; case 22: // 取消粗体/暗淡 isBold = false; break; case 4: // 启用下划线 isUnderline = true; break; case 24: // 取消下划线 isUnderline = false; break; case >= 30 and <= 37: // 标准前景色 currentForeColor = GetAnsiColor(param, false); break; case >= 40 and <= 47: // 标准背景色 currentBackColor = GetAnsiColor(param, true); break; case >= 90 and <= 97: // 高亮度前景色 currentForeColor = GetAnsiColor(param, false); break; case >= 100 and <= 107: // 高亮度背景色 currentBackColor = GetAnsiColor(param, true); break; } } } } lastIndex = match.Index + match.Length; } // 插入剩余的文本 if (lastIndex < ansiText.Length) { string plainText = ansiText.Substring(lastIndex); rtb.SelectionStart = rtb.TextLength; rtb.SelectionLength = 0; rtb.SelectionColor = currentForeColor; rtb.SelectionBackColor = currentBackColor; rtb.SelectionFont = new System.Drawing.Font(originalFont, isBold ? System.Drawing.FontStyle.Bold : isUnderline ? System.Drawing.FontStyle.Underline : System.Drawing.FontStyle.Regular); rtb.SelectedText = plainText; } // 恢复控件初始样式,避免后续手动输入继承当前格式 rtb.SelectionColor = originalForeColor; rtb.SelectionBackColor = originalBackColor; rtb.SelectionFont = originalFont; } }
使用方式
在WinForms项目中,直接调用扩展方法将带ANSI格式的PowerShell输出插入到RichTextBox:
// 假设已捕获带ANSI格式的PowerShell输出 string powerShellOutput = "你的PowerShell输出内容"; richTextBox1.AppendAnsiText(powerShellOutput);
该实现支持常见的ANSI SGR格式:标准/高亮度前景色、背景色、粗体、下划线及样式重置,同时支持跨线程调用(适配后台执行PowerShell时的UI更新场景)。
内容的提问来源于stack exchange,提问作者user22473069
相关产品推荐
相关产品推荐

