You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 19:52:46