如何停止`powershell`将输出包装在ANSI序列中?

4

我使用CreateProcess(win32)创建了一个powershell进程,并从其中读取原始字节。

但是我发现它产生了大量不可见字符,例如\u{1b}[2J\u{1b}[m\u{1b}[

有没有办法停止这种情况发生?

*确实可以手动去除这些字符,但我希望还有其他方法。

2个回答

11
  • 你提到了powershellpowershell.exe),即Windows PowerShell的CLI。

  • Windows PowerShell(与PowerShell(Core)7+不同,见下文)本身不使用基于VT / ANSI转义序列的着色/格式化

  • 这意味着在你的情况下第三方代码正在生成VT序列,因此您必须停用(或重新配置)以避免输出中出现这些序列。

    • 一个主要候选人是自定义的prompt函数;这些函数通常涉及着色以获得更好的命令行体验。

    • 然而,在对powershell.exe进行编程式使用时,只有当您将PowerShell命令传递给CLI的stdin时,才会看到提示函数打印的内容,同时还需要通过向CLI传递参数-File -(指示它从stdin读取命令)或默认方式。

    • 要完全排除提示函数的输出,请使用-Command -,如您之前问题的答案中所讨论的。

    • 如果您确实想要它,但希望使用默认提示字符串,请使用-NoProfile参数来禁止加载$PROFILE,这通常在编程处理中更可取。


在PowerShell(Core)7.2+中控制使用彩色输出(VT / ANSI转义序列)
在PowerShell(Core)7+(pwsh.exe)中,但不包括Windows PowerShell(powershell.exe),PowerShell本身根据情况使用VT(ANSI)转义序列来生成格式化/彩色输出,例如在{{link1:Select-String}}的输出中以及在v7.2+中的格式化输出中,特别是表格输出的列标题/列表输出的属性名称。
  • PowerShell 7.2+ 中,你可以以下方式明确地抑制它们:

    • 注意:通常不需要明确地禁用 VT (ANSI) 序列,因为当输出未发送到主机(显示)时,PowerShell自动抑制它们;也就是说,$PSStyle.OutputRendering 默认为 Host[1]

      • 这相当于许多 Unix 实用程序(合理地)表现出的相同行为:只有在打印到显示(终端)时才应用颜色,而在管道输出到另一个命令或重定向到文件时不应用颜色。
      • 然而,需要注意的是,$PSStyle.OutputRendering 仅适用于由 PowerShell 的 for-display formatting system 格式化的对象,且仅在将此类格式化表示转换为字符串数据时才适用,无论是通过 Out-String 显式转换,还是通过 > / Out-File 隐式转换,或者当管道到一个外部程序时。[2]
    • 从 PowerShell 外部启动之前

      • 通过定义 NO_COLOR 环境变量,并设置为任意值,如 1

        • 这会使 PowerShell 在启动时将 $PSStyle.OutputRendering 设为 PlainText,指示 PowerShell 不使用 VT / ANSI 转义序列。

        • 越来越多的外部程序也遵循该环境变量 - 请参考 no-color.org

      • 或者,通过将 TERM 环境变量设置为 xtermm / xterm-mono(也会将 $PSStyle.OutputRendering 设置为 'plaintext'):

        • 需要注意的是,至少在 PowerShell Core 7.3.3 中,值 dumb 并不起作用:尽管它确实导致 $host.UI.SupportsVirtualTerminal 反映出 $false(正如文档中所述),但 $PSStyle.OutputRendering 仍保持其默认值 Host,并且实际格式化输出(例如来自 Get-Item / 的输出)仍使用颜色。
        • 然而,设置 TERM 可能比 NO_COLOR 在让外部程序不发出 VT 序列方面更有效 - 但最终无法保证。
        • 话虽如此,通常最好避免修改 TERM,尤其是将其设置为值 dumb,因为外部程序(在类 Unix 平台上)可能依赖于 TERM 变量来推断托管终端应用程序的(非与颜色相关的)功能和特性(将变量设置为 dumb 将完全消除这些推断,而值 xtermm / xterm-mono 请注意,使用VT序列的第三方PowerShell代码,特别是在PowerShell(Core)7+之前的版本中,可能不会遵守上述任何用于禁用它们的标准机制(尽管可能提供自定义机制)。

          [1] 这适用于 v7.2.0-preview.9 及以后的版本,其中 Host 成为默认选项,而之前的默认选项 Automatic 已被完全移除。在 v7.3.0 的预览版本中,Ansi 暂时成为默认选项,但自官方 v7.3.0 版本发布后,(明智的)默认选项又变回了 Host

          [2] 值得注意的是,在 v7.3+ 中,带有嵌入 ANSI / VT 转义序列的 字符串 数据不再受到 $PSStyle.OutputRendering 的影响(这是从 v7.2 版本起的更改),因为字符串不受格式化系统处理(它们按原样打印)。


3
您可以通过将环境变量TERM设置为dumb禁用ANSI输出渲染
SetEnvironmentVariable(TEXT("TERM"), TEXT("dumb"));
// proceed with your call to CreateProcess

我想这就是我在寻找的。 然而,SetEnvironmentVariable并不像你所描述的那样起作用。我是这样做的[System.Environment] :: SetEnvironmentVariable(“TERM”,“dumb”)但并非所有序列最终都会被剥离(如果有):(存在不可见字符在结束行之前和之后“\u{1b} [9X \ r \ n \ u{1b} [31X \ r \ nEXPECTED_PROMPT> \ nPing统计信息8.8.8.8:\u{1b} [28X \ r \ n” - Zhiburt
+1 对于一般的指针,虽然我不认为它们适用于这里;即使它们适用(PowerShell(Core)7.2+及其预览版本),答案也是:很复杂。 - mklement0
这对我来说在Windows PowerShell中停止彩色输出很有效。谢谢。 - Hossein Margani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接