【问题标题】:Is there a way to make windows output ansi escape sequences有没有办法让 windows 输出 ansi 转义序列
【发布时间】:2014-05-11 17:03:52
【问题描述】:

有没有办法让 Windows 在内部控制台颜色更改后输出 ansi 转义序列? 我知道像 ansicon 这样的东西,它会解释正在运行的程序输出的 ansi 转义序列,但我想知道 Windows 是否有办法通过标准输出转发这些转义序列。 例如


#include 
#include 
using namespace std;
HANDLE hCon;

enum Color { DARKBLUE = 1, DARKGREEN, DARKTEAL, DARKRED, DARKPINK, DARKYELLOW, GRAY, DARKGRAY, BLUE, GREEN, TEAL, RED, PINK, YELLOW, WHITE };

void SetColor(Color c){
        if(hCon == NULL)
                hCon = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hCon, c);
}

int main()
{
    std::cout "\x1b[31;1m  I should be red if printed on the console, otherwise I should have passed that ansi code to stdout.\n";
    SetColor(GREEN);
    cout "I should be green if printed on the console, but I should have passed the escape sequence to the stdout pipe..\n";
    char x;
    std::cin.get(x);
}

我希望在标准输出上发送的字节级数据采用所有 ansi 批准的文本,包括颜色代码和光标移动转义序列。我什至不确定这是可能的,但如果有人知道的话……这里就是知道它是否已经完成的地方。我也愿意自己滚动并将其添加到 ansicon。

【问题讨论】:

  • @Hans Passant:我不认为这个问题与您将其标记为重复的问题重复。虽然相似,但有一些关键的定义方面。您链接到的问题是如何对您的程序进行编程以输出 ascii。我一直在寻找一种方法让已经编译的程序给我 ansii 代码。
  • @Hans Passant:这个问题不是重复的;它试图解决您所链接问题的相反方向。

标签: c++ windows cmd console ansi


【解决方案1】:

我很确定,自 Windows 2000 以来,任何 Windows 操作系统都没有附带任何内容,包括对 ANSI Escape 序列的支持。

这也是有道理的,如果你考虑 ANSI http://www.roysac.com/learn/ansisys.html 的限制,只有 16 种颜色(已修复),其中只有 8 种可用作背景颜色等。

除非您需要向后兼容很久以前或出于怀旧原因(最后一个类别实际上包括我自己:)),否则没有理由使用 ANSI 转义序列。

如果您查看文档(链接),您还将了解到旧的 ANSI 内容不是很直观和易于使用,当然也不是直截了当的。旧的 PCBoard ANSI 等效编码 @X00 .. @X7F(@X 而不是 CHR(27) "ESC" 然后是 1 字节 BackColor (Hex) 和 1 byte ForeColor (Hex)相比之下,公园:)

【讨论】:

  • 出现这种情况的全部原因是我希望为不运行增强环境的 Windows 开源一个 ssh 服务器。咳咳 CYGWIN 咳,尽可能接近通过 ssh 在 Windows 机器上运行 cmd 的东西。 AFIK,ssh 使用 ascii 代码进行颜色和光标放置。所以,我想真正的问题是,是否有某种好的移植层可以将 .cmd 移植到 ssh 通道可以使用的东西中。
  • 附言。如果您需要参考,我正在谈论的付费版本是 Bitvise。
  • 我不相信 SSH 协议要求 ANSI 转义序列用于颜色/光标放置。颜色/光标放置的概念取决于在 SSH 中运行的应用程序;通常,该应用程序通过ncurses/termios 对转义序列做出假设。在 Windows NT 系列上,应用程序使用控制台 API 而不是 ncurses/termios。据我所知,SSH 最深入的领域是通过pty-reqwindow-change 消息类型。
  • 假设您是正确的,您很可能是正确的。这仍然留下了如何检测那些较低级别的调用的问题,以便可以采取适当的行动,即使该行动不再涉及使用 ansi 颜色代码等。
  • 查看我提供的另外两个答案。 stackoverflow.com/a/23915607/314104 中的答案之前在 KTS 中已经完成,并且确实有效,尽管它不是很干净。 stackoverflow.com/a/23788965/314104 中的答案可能更干净;如果不能使用Detours,可以考虑stackoverflow.com/a/4975615/314104中提到的策略。
【解决方案2】:

虽然这有点麻烦,但您可以通过使用 Detours 并发出适当的 ANSI 转义序列来解决它。在调用控制台 API 函数时,您将向标准输出流发出适当的转义序列。

(我希望有人提出更好的答案,因为虽然这应该可行,但这是一个可怕的黑客攻击。)

【讨论】:

【解决方案3】:

我在开源KpyM Telnet/SSH Server 中看到的一种方法是使用GetConsoleScreenBufferInfoReadConsoleOutput

KTS 不是操纵控制台 I/O 例程来发出终端转义序列,而是创建一个新的控制台窗口并通过它拥有的句柄和GetConsoleScreenBufferInfo(光标信息)和ReadConsoleOutput(on-屏幕信息,包括颜色)功能。捕获数据后,KTS 向远程端发出适当的终端转义序列以重现显示。

此行为不需要 Win32 API 中提供的挂钩,并且适用于交互式应用程序,但它可能会导致屏幕“撕裂”,尤其是当大量输出转储到控制台并且 SSH 守护程序不可用时t 轮询速度足以跟上。此外,由于此机制使用轮询,因此会消耗更多功率,尤其是在充当服务器的移动设备上,以及在具有简单服务器实现的移动客户端上。 (智能服务器实现可以检测到没有任何变化,从而减少发送到移动客户端的数据。)

如果您计划为 Windows 实现(或已经实现)SSH 守护程序,请不要忘记并非所有应用程序都需要此终端仿真行为 - 只有当您收到 pty-req 消息时,此终端仿真才会完成。如果您没有收到pty-req 消息,则 SSH 守护进程应该只中继标准输入/标准输出/标准错误流。

【讨论】:

    猜你喜欢
    • 2019-08-28
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多