0

I am trying to write a console app in VB.NET (VS Studio Community 2019 & .Net framework 4.8) I cannot get it to display ANSI Escape sequences correctly. I am aware of this suggestion and have applied it. (Makes no difference)

I am able to set colour using

Console.ResetColor()
Console.ForegroundColor = ConsoleColor.Red

and cursor positioning, using

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

When I try to do this

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

It just prints it out raw without interpreting the ANSI Sequences.

Console.OutputEncoding = Text.Encoding.XXX only gives me limited options for XXX, including Ascii, UTF8, 16, 32 and Unicode.

I have gone over This article on "Console Virtual Terminal Sequences", which seems to be Microsoft's term for ANSI Codes. This article refers to setConsoleMode.

There is also this snippet of C, for which I can find no equivalent in 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();
    }

I'm guessing that one of these two might be the answer to my problem, but I have no idea how to do anything with this info in VB.net.

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
John Dovey
  • 21
  • 5

1 Answers1

0

The question title indicates the programming is VB.net. Yet this statement is shown

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

in which the C# style unicode escape sequence, \u001b is used. VB does not support escape sequences. A proper VB statement using string interpolation and the ChrW Function would be:

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

This will require using the Platform Invoke (PInvoke) feature to call the native api functions. A direct conversion of the snippet is wrapped in the SetVT100Mode method defined below. You can find the various constants in either the documentation or by looking at the examples at 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
TnTinMn
  • 11,522
  • 3
  • 18
  • 39
  • Fantastic. Thank you! The first issue you pointed out, using ChrW(&H1B), is a major leap forward for me. I have no idea why I haven't spotted that anywhere before! – John Dovey Mar 02 '21 at 18:09
  • Your "Pinvoke" code, I saved as a test program and it compiled and ran perfectly! Thank you once again. – John Dovey Mar 02 '21 at 18:24