为什么有时在CMD中使用ANSI转义码

问题描述

在cmd中,认情况下,Ansi转义码不起作用。

但是,某些应用程序会执行某种初始化,然后在该会话期间它们似乎可以工作。

他们如何进行初始化? 这是一个示例-

我构建了一个简单的防锈应用程序,用于ansi代码以实现彩色输出

Image showing cargo using ansi escape codes.

但是,如果我首先构建项目,然后关闭该会话,然后再次启动cmd进入我的已编译项目所在的目录,然后运行可执行文件(这次在此会话中完全不使用载货)->

Ansi escape codes without cargo

似乎像cargo这样的应用程序(以及其他应用程序)也在cmd中执行某种初始化步骤,此后cmd似乎可以识别ansi代码

并且也在python中 在使用ansi转义码之前调用os.system('')可以完成工作-

ansi escape codes work after os.system('')

os.system('')似乎是一个错误,您不应依靠错误来使代码正常工作。有没有更好的方法可以在cmd中初始化ansi转义代码

解决方法

您要搜索的是ENABLE_VIRTUAL_TERMINAL_PROCESSING。它有时“停止工作”的原因是因为某些应用程序在退出之前禁用了它。如果它已经启用,那么这就是问题所在。

但是,您可以通过使用 SetConsoleMode() 调用 winapi crate 轻松地(再次)启用它。您也可以使用 winapi-util crate,这样会更容易一些。

#[cfg(windows)]
pub fn enable_virtual_terminal_processing() {
    use winapi_util::console::Console;

    if let Ok(mut term) = Console::stdout() {
        let _ = term.set_virtual_terminal_processing(true);
    }
    if let Ok(mut term) = Console::stderr() {
        let _ = term.set_virtual_terminal_processing(true);
    }
}
[target.'cfg(windows)'.dependencies]
winapi-util = "0.1"

为了安全,您可以最初在 enable_virtual_terminal_processing() 中调用 main()。但是,我绝对建议在执行 std::process::Command 后调用它,例如:

let output = Command::new("...")
    .args(&["..."])
    .output()
    .expect("failed to execute process");

#[cfg(windows)]
enable_virtual_terminal_processing();