为啥 Visual Studio 在调试时会以不同的方式处理 ANSI Escape 代码?

Posted

技术标签:

【中文标题】为啥 Visual Studio 在调试时会以不同的方式处理 ANSI Escape 代码?【英文标题】:Why does Visual Studio treat ANSI Escape codes differently when debugging?为什么 Visual Studio 在调试时会以不同的方式处理 ANSI Escape 代码? 【发布时间】:2016-03-24 21:58:59 【问题描述】:

适用于:

Visual Studio 社区版 2015 (C++) Windows 10

Visual Studio 有两种方法可以为 Win32 控制台运行 C++ 程序:“开始不调试 (Ctrl+F5)”和“开始调试 (F5)”。两者都将为程序启动一个单独的控制台窗口。如果程序通过cout 发送 ANSI 转义码,第一个窗口会按预期工作,但第二个窗口会将代码显示为字符,其中不可打印的代码(如 ESC)被方框中的问号替换。

为什么不一样?有没有办法让 ANSI 转义码在调试时正常运行?

【问题讨论】:

它为什么起作用并不明显,ansi.sys 是古老的历史。更好地描述您的运行时环境。 这是 Windows 10 Pro 和 Visual Studio 的库存安装。我正在检查的代码使用 "\033[2J\033[1;1H" 来清除屏幕,其中 \033 是 ESC 的八进制。我无法解释为什么它适用于 F5 方法;我注意到当我在 Visual Studio 之外运行 .exe 时它也不起作用。 是的,你需要忘记这个。 忘了什么?我没有编写这段代码,当劝阻作者不要使用 ANSI 代码时,我更愿意解释为什么它的行为不一致,而不是仅仅指出它确实如此。如果真的有办法让他们继续工作,也许自己也能学到一些东西。 【参考方案1】:

2015 年的文档并没有说有限制(早期版本需要付费版本)。

使用 Visual Studio,您可以使用调试器附加到正在运行的进程,这将避免该问题 - 前提是您的程序可以初始化并等待您执行此操作。

至于为什么不同,那可能是因为调试器正在拦截控制台窗口中运行的程序的输入/输出(并阻止它改变 I/O 模式)。

进一步阅读:

Attach to Running Processes with the Visual Studio Debugger (2015) How to: Attach to a Running Process (2010)

从后续 cmets 中,@Sean-Gugler 意识到

在本机运行时(例如,从文件资源管理器打开),可执行文件的 ANSI 代码未被解释, 但在从 Visual Studio 运行正常时工作。

在被提醒 Windows 10 console window 解释 ANSI 转义序列时,

他验证了可执行文件在控制台窗口中按预期运行,并且 推测 Visual Studio 在调试 (F5) 时直接运行可执行文件(没有控制台窗口),但 确实 在运行可执行文件时在控制台窗口中运行它通常 (ctrlF5)。

从 GUI(例如 Visual Studio)启动控制台应用程序的一个问题是应用程序必须做一些额外的工作来分配控制台。

进一步阅读:

Can one executable be both a console and GUI application? Using the console in a GUI app in windows, only if its run from a console How to write to the console in a GUI application

【讨论】:

经过进一步调查,我发现 .exe 在本机运行时也不会解释 ANSI 代码,只有在 Visual Studio 中运行时没有调试器。很好奇。 据报道 Windows 10 控制台窗口可以解释 ANSI 序列。 这有帮助!我现在看到,如果我从“CMD”控制台运行 .exe,我会得到 ANSI 解释,但如果我双击 .exe,我不会。所以我打赌 Visual Studio 直接使用 F5 启动,但为 Ctrl+F5 运行 CMD shell。 听起来不错(一位用户向我提到了这一点,它在我的待办事项列表中以在ncurses 中正确记录)。 如果你想写/编辑一个答案来包含这些发现,我会接受你的功劳,否则我只会粗鲁地回答我自己的问题。

以上是关于为啥 Visual Studio 在调试时会以不同的方式处理 ANSI Escape 代码?的主要内容,如果未能解决你的问题,请参考以下文章

Visual Studio 2012 不同的值发布/调试模式

为啥 Roslyn 在尝试重写此 lambda 时会崩溃? (Visual Studio 2015 更新 1)

为啥Visual Studio在声明字符串数组列表时会抛出异常

Visual Studio 代码编辑器中的问题。为啥我保存文件时会关闭它们?

为啥 Visual Studio 不能在“不调试就启动”模式下打开文件?

为啥我不能在没有安装Visual Studio的机器上运行调试版的.NET程序