Jump to content

ConsoleWrite and ANSI Escape Sequences Work -- in Windows Terminal


Recommended Posts

I recently noticed that ConsoleWrite can use ANSI escape sequences to output colorful text in a cmd.exe window running in Windows Terminal (WT), but not to a cmd.exe window running under Windows Console Host (WCH). In WT you see colorful text; in WCH the ANSI escape sequences are written out literally. This raises two questions:

1) What's different about WT?

2) It would be nice if there were a conclusive test to determine whether an AutoIt console script is running in WT or WCH. I've tried testing if @AutoItPID is a child process of WindowsTerminal.exe, but it isn't, even if the AutoIt console script is running in a WT tab -- so no joy. Any ideas?

Func _ConsoleWriteANSI($sTxt, $iFg1 = 33, $iBg1 = 1, $iFg0 = 22, $iBg0 = 0)
; Write colorful text to the cmd.exe window (default = Bright Yellow on Black)
; Compile AutoIt script as a console app!
; Colors work in Windows Terminal (WT), not in Windows Console Host
; So: Set Global $bANSI = 1 if script is running in WT
    If Not $bANSI Then
        ConsoleWrite($sTxt)
    Else
        ConsoleWrite(Chr(27) & "[" & $iFg1 & "m" & Chr(27) & "[" & $iBg1 & _
            "m" & $sTxt & Chr(27) & "[" & $iFg0 & "m" & Chr(27) & _
            "[" & $iBg0 & "m")
    EndIf
    Return
EndFunc  ;==>_ConsoleWriteANSI

 

Edited by CarlD
Link to comment
Share on other sites

This is working for me :

ConsoleWrite(_WinAPI_GetProcessName(_WinAPI_GetParentProcess (_WinAPI_GetParentProcess (@AutoItPID))) & @CRLF)

gives WindowsTerminal.exe or explorer.exe or Scite.exe

Edited by Nine
Link to comment
Share on other sites

7 hours ago, Nine said:

This is working for me :

ConsoleWrite(_WinAPI_GetProcessName(_WinAPI_GetParentProcess (_WinAPI_GetParentProcess (@AutoItPID))) & @CRLF)

gives WindowsTerminal.exe or explorer.exe or Scite.exe

Thanks, this is helpful. On my system (Win 10 Pro v10.0.19045.4651), this returns "WindowsTerminal.exe" if Windows Console Host is the default terminal application. However, it returns "cmd.exe" if Windows Terminal is the default. I'm pressed for time just now, but a quick search did not turn up any way to determine the default terminal app programmatically. Will do some further research soon.

Link to comment
Share on other sites

#include <WinAPIProc.au3>

_ConsoleWriteANSI("Hello there !." & @CRLF) ; as is, will need compilation for testing
Func _ConsoleWriteANSI($sTxt, $iFg1 = 33, $iBg1 = 1, $iFg0 = 22, $iBg0 = 0)
; Write colorful text to the cmd.exe window (default = Bright Yellow on Black)
; Compile AutoIt script as a console app!
; Colors work in Windows Terminal (WT), not in Windows Console Host
; So: Set Global $bANSI = 1 if script is running in WT
    Local Static $bANSI = Am_I_in_WT() ; only used here ?, keep it here ?
    If Not $bANSI Then
        ConsoleWrite($sTxt)
    Else
        ConsoleWrite(Chr(27) & "[" & $iFg1 & "m" & Chr(27) & "[" & $iBg1 & _
            "m" & $sTxt & Chr(27) & "[" & $iFg0 & "m" & Chr(27) & _
            "[" & $iBg0 & "m")
    EndIf
    Return
EndFunc  ;==>_ConsoleWriteANSI

Func Am_I_in_WT() ; WindowsTerminal.exe
    Local $n, $iParentPID = @AutoItPID
    For $n = 1 To 99
        $iParentPID = _WinAPI_GetParentProcess($iParentPID)
        If $iParentPID = 0 Then ExitLoop
        If _WinAPI_GetProcessName($iParentPID) = "WindowsTerminal.exe" Then Return 1
    Next
EndFunc
Spoiler

pre-edit idea:

#include <Array.au3>
#include <WinAPIProc.au3> ; _GetParentProcessTree() example mod.
_ArrayDisplay(_GetParentOfMine(), "_GetParentOfMine", "", 0, Default, "PID|Name|CommandLine")
Func _GetParentOfMine($iPID = @AutoItPID)
    Local $iFound = 0, $n, $iParentPID = $iPID, $aList[100][3]
    $aList[0][0] = $iPID
    $aList[0][1] = _WinAPI_GetProcessName($iPID)
    $aList[0][2] = _WinAPI_GetProcessCommandLine($iPID)
    For $n = 1 To 99
        $iParentPID = _WinAPI_GetParentProcess($iParentPID)
        If $iParentPID = 0 Then ExitLoop
        $aList[$n][0] = $iParentPID
        $aList[$n][1] = _WinAPI_GetProcessName($iParentPID)
        $aList[$n][2] = _WinAPI_GetProcessCommandLine($iParentPID)
        If $iFound = 0 And ($aList[$n][1] <> "AutoIt3.exe" And $aList[$n][1] <> "AutoIt3_x64.exe") Then
            $iFound = 1
            $aList[$n][1] = '-->' & $aList[$n][1] & '<--' ; found my parent
        EndIf
    Next
    ReDim $aList[$n][3]
    Return $aList
EndFunc   ;==>_GetParentOfMine
Edited by argumentum
better

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

Posted (edited)

I appreciate the sample code -- many thanks. In the meantime, I found a workaround that supports writing ANSI colorful text to the console in both Windows Terminal and Windows Console Host. The trick is to save the text to a temp file and then type the file.

#include <File.au3>
#include <FileConstants.au3>
#include <Process.au3>

Func _ConsoleWriteANSI($sTxt, $iFg1 = 33, $iBg1 = 1, $iFg0 = 22, $iBg0 = 0)
; Write colorful text to the console ("TYPE tmp_file" method)
; Default color - Bright Yellow on Black background
    Local $h, $sTmpFn = _TempFile(@ScriptDir)
    $h = FileOpen($sTmpFn, $FO_BINARY + $FO_OVERWRITE)
    If $h < 0 Then Return ConsoleWrite($sTxt)
    If Not FileWrite($h, Chr(27) & "[" & $iFg1 & "m" & Chr(27) & _
        "[" & $iBg1 & "m" & $sTxt & Chr(27) & "[" & $iFg0 & "m" & _
        Chr(27) & "[" & $iBg0 & "m") Then
        FileClose($h)
        Return ConsoleWrite($sTxt)
    EndIf
    FileClose($h)
    _RunDos("type " & $sTmpFn)
    FileDelete($sTmpFn)
EndFunc  ;==>_ConsoleWriteANSI

 

Edited by CarlD
Link to comment
Share on other sites

Posted (edited)

Another way -- no file required. BUT: does not work if text includes newlines!

Edit: Here's a workaround for text that includes newlines. In the final analysis, the "TYPE temp_file" method is more compact and straight-forward.

#include <Process.au3>
#include <StringConstants.au3>

_ConsoleWriteANSI("This is Line #1." & @CRLF)
_ConsoleWriteANSI("This is Line #2." & @CRLF, 33, 104)
_ConsoleWriteANSI("This is Line #3a," & @CRLF & "and this is Line #3b" & @CRLF, 41, 52)
_ConsoleWriteANSI("This is Line #4." & @CRLF, 105, 35)

Func _ConsoleWriteANSI($sTxt, $iFg1 = 33, $iBg1 = 1, $iFg0 = 22, $iBg0 = 0)
; Write colorful text to the console ("ECHO" method)
; Reserved chars ^&|()<> must be "escaped" with ^
; Default color - Bright Yellow on Black background
    Local $aLines, $iNL = 0, $sDummy = Chr(254) & Chr(15) & Chr(255)
    Local $aResvChar = StringSplit("^&|()<>", ""); "^" must come first!
    While StringRight($sTxt, 2) = @CRLF
        $sTxt = StringTrimRight($sTxt, 2)
        $iNL += 1
    WEnd
    $sTxt = Chr(27) & "[" & $iFg1 & "m" & Chr(27) & _
        "[" & $iBg1 & "m" & $sTxt & Chr(27) & "[" & $iFg0 & "m" & _
        Chr(27) & "[" & $iBg0 & "m"
    For $i = 1 To $aResvChar[0]
        $sTxt = StringReplace($sTxt, $aResvChar[$i], "^" & $aResvChar[$i])
    Next
    If StringInStr($sTxt, @CR) Or StringInStr($sTxt, @LF) Then
        $sTxt = StringReplace($sTxt, @CRLF, $sDummy)
        $sTxt = StringReplace($sTxt, @CR, $sDummy)
        $sTxt = StringReplace($sTxt, @LF, $sDummy)
        $sTxt = StringReplace($sTxt, $sDummy, @CRLF)
        While StringLeft($sTxt, 2) = @CRLF
            ConsoleWrite(@CRLF)
            $sTxt = StringTrimLeft($sTxt, 2)
        WEnd
        $aLines = StringSplit($sTxt, @CRLF, $STR_ENTIRESPLIT)
        For $i = 1 To $aLines[0]
            _RunDos("echo " & $aLines[$i])
        Next
    Else
        _RunDos("echo " & $sTxt)
    EndIf
    If $iNL > 1 Then
        For $i = 2 To $iNL
            ConsoleWrite(@CRLF)
        Next
    EndIf
EndFunc  ;==>_ConsoleWriteANSI

 

Edited by CarlD
Better code for leading & trailing newlines
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...