Open GregorLamche opened 2 years ago
Tagging subscribers to this area: @dotnet/area-system-console See info in area-owners.md if you want to be subscribed.
Author: | GregTheMad |
---|---|
Assignees: | - |
Labels: | `area-System.Console`, `untriaged` |
Milestone: | - |
Have you compared other programs that writes different colors into console? Those console are implemented in very different ways, and will have different compatibility.
I tried it in various terminals, but only with my small program written in the Reproduction Steps. I did however notice that the ASP.Net Core default debug output manages to correctly format the output for the VSC Debug Console output, while Console.Foreground does not. A C++ library I was using (wrapped in C#) also managed to correctly format the output for the VSC Debug Console. Visual Studio Code Debug Console is the only terminal so far that I discovered where Console.Foreground does not work, while the Unicode approach does work (which is why I guess it's a DotNet issue and not a VSC issue).
Console in Windows and console in Unix are fundamentally different. Using control character is Unix-like way, and VSCode is more Unix-like. The others are mostly native Windows console. This may be a cross compatibility issue.
It's hard to tell. ASP.NET Core outputs the color in VSC Debug Console correctly, so it either has some hidden secret sauce, or I'm missing something. In the VSC Terminal (which I think is a wrapped external terminal?) for example the Console.Foreground gets correctly displayed. As a program I have no idea (and I guess I shouldn't) in what type of terminal I'm running (eg. Unix or Windows), and so I can't handle the different support myself. The DotNet Runtime need to do this for me.
It would be interesting to look at what aspnet is doing differently.
Yes, I had similar issues in the past and I don't think anything has changed since then. Since about 6 months ago.
Sometimes setting colors directly works. Sometimes sending ANSI codes works. Sometimes only basic ANSI codes work, sometimes also extended (like bold/italic/enhanced-color) codes work.
Now, it's not so much a problem to put all in a helper function that uses different approaches for coloring, but in Core there is really no good way to determine "where you are", what is supported and what is not. That terminal information is provided by the operating system, as tools like compilers (gcc, clang, you name it) know exactly if they can print ANSI codes or not. Or if enhanced ANSI codes are supported. As far as I know ForegroundColor is Windows-only anyway. As are all cursor ("caret") features.
Unification, or console feedback of supported features is really missing. Best would be if Core would emit ANSI when on non-Windows and the terminal supports it. Not just color, but cursor ("caret") movement as well.
And then there is the new Terminal Window and all its issues with Core.
If anyone's still having an issue with this, just printing the ANSI reset code near the start of the app boot fixed on Windows using the new terminal.
Console.Write("\x1b[0m");
Any updates to this? I am interested in a clean way to change colors in VScode's Debug console
Hi ! If you want to use rgb colors with the native windows terminal, you need to enable VT100 support first. source : https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences See the "Extended Colors" section to format your escape sequence.
To do it, you can import some methods from kernel32.dll directly. Simply call TerminalSetup.Setup(), it worked for me on Windows 10 with vs2019, vs2022, cmd, powershell, the new windows terminal and through puTTy as well.
public class TerminalSetup
{
// ReSharper disable InconsistentNaming
private const int STD_INPUT_HANDLE = -10;
private const int STD_OUTPUT_HANDLE = -11;
private const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
private const uint DISABLE_NEWLINE_AUTO_RETURN = 0x0008;
private const uint ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200;
// ReSharper restore InconsistentNaming
[DllImport("kernel32.dll")]
private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
[DllImport("kernel32.dll")]
private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll")]
public static extern uint GetLastError();
public static void Setup()
{
var iStdIn = GetStdHandle(STD_INPUT_HANDLE);
var iStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (!GetConsoleMode(iStdIn, out uint inConsoleMode))
{
Console.WriteLine("failed to get input console mode");
Console.ReadKey();
return;
}
if (!GetConsoleMode(iStdOut, out uint outConsoleMode))
{
Console.WriteLine("failed to get output console mode");
Console.ReadKey();
return;
}
inConsoleMode |= ENABLE_VIRTUAL_TERMINAL_INPUT;
outConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN;
if (!SetConsoleMode(iStdIn, inConsoleMode))
{
Console.WriteLine($"failed to set input console mode, error code: {GetLastError()}");
Console.ReadKey();
return;
}
if (!SetConsoleMode(iStdOut, outConsoleMode))
{
Console.WriteLine($"failed to set output console mode, error code: {GetLastError()}");
Console.ReadKey();
return;
}
}
}
Description
When setting the output color with Console.Foreground not every terminal correctly displays the color. However if the color is set with unicode characters like \u001b[31m those terminals do show the correct color, meaning they do support color. (but some Terminals display the characters instead of the color making it not a functional workaround)
Reproduction Steps
Expected behavior
Console.Foreground should correctly set the font color independent of terminal, or at least in all terminals that support font colors.
Actual behavior
In some terminals Console.Foreground works, in some it doesn't. In some terminals \u001b[31m works, in some it doesn't. These two collections are not the same. The user doesn't know in which type of terminal the code is running. There is no way to consistently set color in the terminal.
Regression?
No response
Known Workarounds
None, see Actual behavior.
Configuration
No response
Other information
Tested on net6.0/Windows