4

I am making a tutorial program for a friend of mine using batching programming. I would like to know if it is possible if there is code I can write in the file that will display the current color code.

Example being the color is currently set to 0A and I want be displayed on the line saying:

echo The color is currently set to 0A.

I want my file to read the code that is set to and display it to help them remember what changes they have made as this is an example program for color codes in the command prompt/batch.

Thank you for your help!

aschipfl
  • 33,626
  • 12
  • 54
  • 99

5 Answers5

5

It is easy to make your own command to do this. Copy both below text files into GetConsoleColour.bat and GetConsoleColour.vb in the same folder. Double click the batch file and it will create GetConsoleColour.exe.

PS Colour is spelt right for my culture. As I'm writing it I don't see any need to use American spelling which in programming you usually have to do.

See https://learn.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo

GetConsoleColour.exe prints the current console colour in hex and returns an errorlevel with the value

To use

C:\PathToFile\GetConsoleColour

I have a program here that sets text color line by line. It is the only technique that will work on all Windows computers.

Command Prompt Scripting: Problem with multiple colors in a batch file.

Also a similar program saying how many processes are in this console window - ListConsole.exe list the processes in the current console and returns an errorlevel saying how many . https://winsourcecode.blogspot.com/2019/05/listconsoleexe-list-processes-in.html


REM GetConsoleColour.bat
REM This file compiles GetConsoleColour.vb to GetConsoleColour.exe
REM GetConsoleColour.exe prints the current console colour and returns an errorlevel with the value
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc.exe" /target:exe /out:"%~dp0\GetConsoleColour.exe" "%~dp0\GetConsoleColour.vb" 
pause

Note: There is only 4 lines of code here. The rest is just information the program needs to do those 4 lines. In a big program they would be hidden away in a separate file.

'GetConsoleColour.vb
Imports System
Imports System.IO
Imports System.Runtime.InteropServices
Imports Microsoft.Win32

Public Module MyApplication 

Public Declare Function GetStdHandle Lib "kernel32" Alias "GetStdHandle" (ByVal nStdHandle As Long) As Long
Public Declare Function SetConsoleTextAttribute Lib "kernel32" Alias "SetConsoleTextAttribute" (ByVal hConsoleOutput As Long, ByVal wAttributes As Long) As Long
Public Declare Function GetConsoleScreenBufferInfo Lib "kernel32" (ByVal hConsoleOutput As Integer, ByRef lpConsoleScreenBufferInfo As CONSOLE_SCREEN_BUFFER_INFO) As Integer
Public Const STD_ERROR_HANDLE = -12&
Public Const STD_INPUT_HANDLE = -10&
Public Const STD_OUTPUT_HANDLE = -11&

 <StructLayout(LayoutKind.Sequential)> _
Public Structure COORD
    Public x As Short
    Public y As Short
End Structure

 <StructLayout(LayoutKind.Sequential)> _
Public Structure SMALL_RECT
    Public Left As Short
    Public Top As Short
    Public Right As Short
    Public Bottom As Short
End Structure

 <StructLayout(LayoutKind.Sequential)> _
Public Structure CONSOLE_SCREEN_BUFFER_INFO
    Public dwSize As COORD
    Public dwCursorPosition As COORD
    Public wAttributes As Integer
    Public srWindow As SMALL_RECT
    Public dwMaximumWindowSize As COORD
End Structure 


Sub Main()
    Dim hOut as IntPtr
    Dim Ret as Integer
    Dim CSBI as Console_Screen_Buffer_Info
    hOut  = GetStdHandle(STD_OUTPUT_HANDLE)
    Ret = GetConsoleScreenBufferInfo(hOut, CSBI)
    Console.Writeline(Hex(CSBI.wAttributes))
    Environment.ExitCode = CSBI.wAttributes
End Sub
End Module
2

As already indicated in another answer, you can use from your to show you the current color sequence:

@(Set/P "=The color is currently set to "<NUL&For /F %%# In ('^""%__AppDir__%WindowsPowerShell\v1.0\powershell.exe" -NoP "$Console=(Get-Host).UI.RawUI;Switch($Console.BackgroundColor,$Console.ForegroundColor){'Black'{'0'}'DarkBlue'{'1'}'DarkGreen'{'2'}'DarkCyan'{'3'}'DarkRed'{'4'}'DarkMagenta'{'5'}'DarkYellow'{'6'}'Gray'{'7'}'DarkGray'{'8'}'Blue'{'9'}'Green'{'A'}'Cyan'{'B'}'Red'{'C'}'Magenta'{'D'}'Yellow'{'E'}'White'{'F'}}" 2^>NUL^"')Do @Set/P=%%#<NUL)&Echo(&Pause

You should also be able to do it from the thus:

(Set/P "=The color is currently set to "<NUL&For /F %# In ('^""%__AppDir__%WindowsPowerShell\v1.0\powershell.exe" -NoP "$Console=(Get-Host).UI.RawUI;Switch($Console.BackgroundColor,$Console.ForegroundColor){'Black'{'0'}'DarkBlue'{'1'}'DarkGreen'{'2'}'DarkCyan'{'3'}'DarkRed'{'4'}'DarkMagenta'{'5'}'DarkYellow'{'6'}'Gray'{'7'}'DarkGray'{'8'}'Blue'{'9'}'Green'{'A'}'Cyan'{'B'}'Red'{'C'}'Magenta'{'D'}'Yellow'{'E'}'White'{'F'}}" 2^>NUL^"')Do @Set/P=%#<NUL)&Echo(
Compo
  • 36,585
  • 5
  • 27
  • 39
  • Though it does work in single use, It's very hit and miss when it's called upon repeatedly in a function. Often it will only return the first component of the code in effect – T3RR0R Dec 26 '19 at 06:43
  • Whilst I'm unable to test it, _so cannot confirm or deny_, I really do find it difficult to believe that anyone would need it more than once, @T3RROR. Why would anyone need it in a function? single use should be it's only use! If I do find time over the seasonal break, I'll take a look at it and see if there's any improvement to be made. You can always enter `color` with no parameters, to return the color to its default, and once you've changed it, you should know what the color is. – Compo Dec 26 '19 at 11:05
  • The reason I tested it as a function is the use the Op described as an example program for a beginner to familiarise themselves with colour codes, indicating the user will be making changes. I was actually hoping it worked, as it seemed an Elegant solution. It struggles most with numerical codes. – T3RR0R Dec 26 '19 at 14:13
  • @T3RR0R, when a user makes a change, they can clearly see the colours in front of them, _(there's only 16 of them after all)_. If someone wants to familiarise themselves, they just need to read the help information for the `color` command. I honestly don't see a need for this at any time, _which probably explains why there's no built-in command in the first place_. I was unaware that the strings had been modified by my predictive text, and have corrected them to remove the invalid spaces. Has that fixed the unnecessary function you tested it against? – Compo Dec 27 '19 at 13:55
  • Does appear to be working Flawlessly now. I'm in complete agreeance regarding it being something there's no particular need for, However the Solution you've presented is quite Elegant for something that Batch alone lacks the native capacity to do. I'm a hobby coder. I enjoy the art of problem solving, and like to Formulate, or discover solutions, or to see the multitude of ways others find solutions to problems, regardless of how trivial they may seem. – T3RR0R Dec 27 '19 at 15:43
0

By making a compromise and using setlocal EnableDelayedExpansion, you can do so using the following:

@ECHO OFF

Setlocal enableDelayedExpansion

Set "Color=Color 02" && !color!

ECHO Color is currently %color%

pause

The downside of this approach being changing console Color becomes a 2 Step process (depending on how your displaying information).

T3RR0R
  • 2,747
  • 3
  • 10
  • 25
  • This can also be done with Set /p to Set the Color, However you then need to validate that the user input is a Valid Color Code. – T3RR0R Dec 25 '19 at 02:14
  • The question is how to determine the current color, _I'm assuming, both fore and background_.?, not to set it to a specific combination! More like 'Your current color combination is 07. Would you like to change it?' – Compo Dec 25 '19 at 02:25
  • As dbenam has said, there's no native way to do so. Had Color information been Included in Mode /Status, A for loop on the output of Mode /Status could have done the Job. When a true solution Doesn't exist, you have to make compromises. – T3RR0R Dec 25 '19 at 02:27
  • Also, The Answer I provided may not Do the action the Question refers to, however it Does achieve the Outcome the question asks for. The Question (Headline, and first component in Body) Asks If it's possible to output the current Colorcode. This answer Outputs the current Color Code. Whilst it does require a Modification in how the Color Code is Applied, It's a small inconvenience given it achieves the goal - Especially when other options are Lacking. – T3RR0R Dec 25 '19 at 02:46
0

@echo off && setlocal EnableDelayedExpansion 

set "_color="0 Black","1 DarkBlue","2 DarkGreen","3 DarkCyan","4 DarkRed","
@set "_color=!_color!"5 DarkMagenta","6 DarkYellow","7 Gray","8 DarkGray","
      set "_color=!_color!"9 Blue","A Green","B Cyan","C Red","D Magenta","
      set "_color=!_color!"E Yellow","F White"" && cd/d "%~dp0" && title %0

;for /f %%I in ('powershell echo "$([console]::ForegroundColor) $([console]::BackgroundColor)"
')do for %%# in (!_color!)do set "_Hex=%%~#"&& for /f %%a in ('cd')do if "%%~I"=="!_Hex:~2!" (
if not "!_FB!"=="!_Hex:~1,1!" ( set "_FB=!_Hex:~0,1!!_FB!" && set "_L= !_Hex:~2!!_L!"))

set "_L=!_L:~1!"&& cmd/v/c echo The color is currently set to !_FB! (!_L: =/!^)&&endlocal

  • Output:

The color is currently set to 0A (Black/Green)

rem :: powershell command :: 
echo "$([console]::BackgroundColor) $([console]::ForegroundColor)"

@echo off && setlocal EnableDelayedExpansion 

set "_color="0 Black","1 DarkBlue","2 DarkGreen","3 DarkCyan","4 DarkRed","
;set "_color=!_color!"5 DarkMagenta","6 DarkYellow","7 Gray","8 DarkGray","
      set "_color=!_color!"9 Blue","A Green","B Cyan","C Red","D Magenta","
      set "_color=!_color!"E Yellow","F White"" && cd/d "%~dp0" && title %0

for /f %%I in ('powershell echo "$Host.UI.RawUI.BackgroundColor $Host.UI.RawUI.ForegroundColor"
')do for %%# in (!_color!)do set "_Hex=%%~#"&& for /f %%a in ('cd')do if "%%~I"=="!_Hex:~2!" (
if not "!_FB!"=="!_Hex:~1,1!" ( set "_FB=!_Hex:~0,1!!_FB!" && set "_L= !_Hex:~2!!_L!"  ))

set "_L=!_L:~1!"&& cmd/v/c echo The color is currently set to !_FB! (!_L: =/!^)&&endlocal

  • Output:

The color is currently set to 0A (Black/Green)

rem :: powershell command :: 
echo "$Host.UI.RawUI.BackgroundColor $Host.UI.RawUI.ForegroundColor"

enter image description here


  • Generate C# .exe in Run Time

This bat file that generate a file cFB.cs (colorForegroundBackground.C#) and in run time, will build the executable cFB.exe for execute them using ConsoleColor Enum


@echo off && setlocal EnableDelayedExpansion 

set "_color="0 Black","1 DarkBlue","2 DarkGreen","3 DarkCyan","4 DarkRed","
@set "_color=!_color!"5 DarkMagenta","6 DarkYellow","7 Gray","8 DarkGray","
      set "_color=!_color!"9 Blue","A Green","B Cyan","C Red","D Magenta","
      set "_color=!_color!"E Yellow","F White"" && cd/d "%~dp0" && title %0

for %%D in (.exe,.cs) do if exist "%temp%\cFB%%~D" (2>nul >nul del /q /f "%temp%\cFB%%~D")
set "_csc=%windir%\Microsoft.NET"&& set "_where=%__appdir__%where.exe" && set "_cs=cFB.cs"
set "_arg=/t:exe /out:"%tmp%\!_cs:~,-3!.exe" "%tmp%\!_cs!" /platform:x86 /unsafe+ /w:0 /o"

set "_c=!_where! /r "!_csc!" "csc.exe" "&& set "_#=%temp%\!_cs!" && cmd/v/c echo=&>"!_#!"^
     (
     echo/ using System; namespace cFB ^{class Program ^{public static void Main(^)^{
     echo/ ConsoleColor currentForeground=Console.ForegroundColor;
     echo/ ConsoleColor currentBackground=Console.BackgroundColor;
     echo/ Console.WriteLine("{0}\n{1}",Console.ForegroundColor,Console.BackgroundColor^);^}^}^}
     ) && (pushd "%temp%" & goto :run)||echo=Well, something is really wrong here^!! & goto :Err

:run
for /f tokens^=* %%i in ('!_c!^|find "k\v2"')do "%%~i" /nologo !_arg!&& if exist "!_#:~0,-3!.exe" (
for /f ^delims^=^ ^eol^= %%r in ('"!_#:~0,-3!.exe"')do set "_Hex=%%r") else (popd && cls 2>nul && (
echo=File: "!_#:~0,-3!.exe" not found, something is really wrong here^^!!& timeout -1& goto :Err) )

for /f tokens^=^*^delims^= %%I in ('"!_#:~0,-3!.exe"')do for %%# in (!_color!)do set "_h=%%~#" && (
if "%%~I"=="!_h:~2!" if not "!_fb!"=="!_h:~0,l!" (set "_fb=!_h:~0,1!!_fb!"&&set "_l= !_h:~2!!_l!"))

set "_l=!_l:~1!" && for %%D in (.exe,.cs) do if exist "%temp%\cFB%%~D" >nul del /q "%temp%\cFB%%~D" 
cmd /v /c echo The color is currently set to: !_fb! (!_l: =/!^) && endlocal && exit /b || goto :EOF

:Err
endlocal & exit /b || goto :EOF

This is C# code without escaping:

using System;
namespace CBF 
{ 
   class Program 
   {
      public static void Main()
      {
         ConsoleColor currentBackground=Console.BackgroundColor;
         ConsoleColor currentForeground=Console.ForegroundColor;
         Console.WriteLine("{0}\n{1}",Console.ForegroundColor,Console.BackgroundColor);
      }
   }
}

  • Bat Run C# Commmand Output:

The color is currently set to: 0A (Black/Green)

  • Command line to build executable:
"C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe" /nologo /t:exe /out:"%temp%\cFB.exe" "%temp%\cFB.cs" /platform:x86 /w:0 /o



You also, can try get some help with $Host.UI.RawUI in ?


@echo off && setlocal EnableDelayedExpansion 

set "_color="0 Black","1 DarkBlue","2 DarkGreen","3 DarkCyan","4 DarkRed","
@set "_color=!_color!"5 DarkMagenta","6 DarkYellow","7 Gray","8 DarkGray","
      set "_color=!_color!"9 Blue","A Green","B Cyan","C Red","D Magenta","
      set "_color=!_color!"E Yellow","F White""&& cd/d "%~dp0" && title %~0

for /f tokens^=2^delims^=^:^  %%I in ('powershell -nOp $Host.UI.RawUI^|find "Color"')do (
for %%# in (!_color!)do set "_Hex=%%~#"&& for /f %%a in ('cd')do if "%%~I"=="!_Hex:~2!" (
if not "!_FB!"=="!_Hex:~1,1!" ( set "_FB=!_Hex:~0,1!!_FB!" && set "_L= !_Hex:~2!!_L!" )))

set "_L=!_L:~1!"&& cmd/v/c echo The color is currently set to !_FB! (!_L: =/!^)&&endlocal


  • Bat File Output:

The color is currently set to A3 (Green/DarkCyan)


rem :: just type :: 
powershell -nop -c "$Host.UI.RawUI"|find "Color"

rem :: or -nop -c
powershell "$Host.UI.RawUI"|find "Color"

  • $Host.UI.RawUI Output:

ForegroundColor       : White
BackgroundColor       : Blue

  • $Host.UI.RawUI Full output:

ForegroundColor       : White
BackgroundColor       : Blue
CursorPosition        : 0,108
WindowPosition        : 0,90
CursorSize            : 25
BufferSize            : 99,770
WindowSize            : 89,48
MaxWindowSize         : 99,50
MaxPhysicalWindowSize : 174,50
KeyAvailable          : False
WindowTitle           : Q59449889v2.cmd - powershell  $Host.UI.RawUI

Sorry my limited English


Io-oI
  • 2,514
  • 3
  • 22
  • 29
  • 1
    instead of writing a C# program, compile and run you can simply run `[console]::BackgroundColor` and `[console]::ForegroundColor` directly in PowerShell to get those properties. Or combine them in a single command like echo `"$([console]::BackgroundColor) $([console]::ForegroundColor)"`. Remember you can call any .NET framework methods in PowerShell – phuclv Jan 17 '20 at 14:58
  • 1
    and instead of `powershell -nop -c "$Host.UI.RawUI"|find "Color"` just use `$Host.UI.RawUI.ForegroundColor` and `$Host.UI.RawUI.BackgroundColor` directly – phuclv Jan 17 '20 at 14:59
0

As a riff on all the powershell answers, you can also pull just the color descriptors by embedding the PS command in a FOR /f command, for example, (where the color is token 3)

setlocal enabledelayedexpansion
@for /f "tokens=3" %%i in ('powershell "$Host.UI.RawUI"^|find "Color"') do (
  set /a _cnt+=1
  IF !_cnt! equ 1 set _colorF=%%i
  IF !_cnt! equ 2 set _colorB=%%i
)
setlocal disabledelayedexpansion
echo %_colorF%
echo %_colorB%
ilinkcs
  • 142
  • 8