VB.NET 控制台:使用 ANSI 序列(控制台虚拟终端序列)

VB.NET Console: Use ANSI Sequences (Console Virtual Terminal Sequences)

我正在尝试在 VB.NET 中编写一个控制台应用程序(VS Studio Community 2019 & .Net framework 4.8) 我无法让它正确显示 ANSI 转义序列。 我知道 this suggestion 并已应用它。 (没有区别)

我可以使用

设置颜色
Console.ResetColor()
Console.ForegroundColor = ConsoleColor.Red

和光标定位,使用

Console.SetCursorPosition(origCol + x, origRow + y)
Console.Write(s)

当我尝试这样做时

Console.WriteLine("\u001b[31mHello World!\u001b[0m")

它只是直接打印出来而不解释 ANSI 序列。

Console.OutputEncoding = Text.Encoding.XXX 只给我有限的 XXX 选项,包括 Ascii、UTF8、16、32 和 Unicode。

我已经过了This article on "Console Virtual Terminal Sequences", which seems to be Microsoft's term for ANSI Codes. This article refers to setConsoleMode.

还有这个 C 代码片段,我在 vb.net

中找不到与之对应的片段
// Set output mode to handle virtual terminal sequences
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hOut == INVALID_HANDLE_VALUE)
    {
        return GetLastError();
    }

    DWORD dwMode = 0;
    if (!GetConsoleMode(hOut, &dwMode))
    {
        return GetLastError();
    }

    dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
    if (!SetConsoleMode(hOut, dwMode))
    {
        return GetLastError();
    }

我猜这两个中的一个可能是我的问题的答案,但我不知道如何使用 VB.net 中的此信息。

题名表示编程是VB.net。然而这个声明显示

Console.WriteLine("\u001b[31mHello World!\u001b[0m")

其中使用了 C# 风格的 unicode 转义序列 \u001b。 VB 不支持转义序列。使用字符串插值和 ChrW Function 的正确 VB 语句将是:

Console.WriteLine($"{ChrW(&H1B)}[31mHello World!{ChrW(&H1B)}[0m")

There is also this snippet of C, for which I can find no equivalent in vb.net

这将需要使用平台调用 (PInvoke) 功能来调用本机 api 函数。片段的直接转换包含在下面定义的 SetVT100Mode 方法中。您可以在文档中或通过查看 Pinvoke.net.

中的示例找到各种常量
Imports System.Runtime.InteropServices

Module Module1
  Private Const STD_INPUT_HANDLE As Int32 = -10
  Private Const STD_OUTPUT_HANDLE As Int32 = -11
  Private Const STD_ERROR_HANDLE As Int32 = -12
  Private ReadOnly INVALID_HANDLE_VALUE As New IntPtr(-1)
  Private Const ENABLE_VIRTUAL_TERMINAL_PROCESSING As UInt32 = &H4

  Sub Main()
    Const Esc As Char = ChrW(27)

    If SetVT100Mode() = 0 Then
      Console.WriteLine($"{Esc}[31mHello World!{Esc}[0m")
    End If

    Console.ReadLine()

  End Sub

  Private Function SetVT100Mode() As Int32
    Dim hOut As IntPtr = GetStdHandle(STD_OUTPUT_HANDLE)
    If hOut = INVALID_HANDLE_VALUE Then
      Return Marshal.GetLastWin32Error()
    End If

    Dim mode As UInt32
    If Not GetConsoleMode(hOut, mode) Then
      Return Marshal.GetLastWin32Error()
    End If

    mode = mode Or ENABLE_VIRTUAL_TERMINAL_PROCESSING
    If Not SetConsoleMode(hOut, mode) Then
      Return Marshal.GetLastWin32Error()
    End If
    Return 0
  End Function

  <DllImport("kernel32.dll", SetLastError:=True)>
  Private Function GetConsoleMode(ByVal hConsoleHandle As IntPtr, ByRef lpMode As UInteger) As Boolean
  End Function

  <DllImport("kernel32.dll", SetLastError:=True)>
  Private Function SetConsoleMode(ByVal hConsoleHandle As IntPtr, ByVal dwMode As UInteger) As Boolean
  End Function

  <DllImport("kernel32.dll", SetLastError:=True)>
  Private Function GetStdHandle(ByVal nStdHandle As Integer) As IntPtr
  End Function

End Module