CONSOLE.BAT - Get and set console window attributes via hybrid batch/powershell

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

CONSOLE.BAT - Get and set console window attributes via hybrid batch/powershell

#1 Post by dbenham » 30 Mar 2016 20:20

This first post contains an outdated version. The current version of CONSOLE.BAT is available here.

Batch has limited ability to get or set console attributes, but PowerShell has extensive control. This hybrid Batch/PowerShell utility brings much of the PowerShell capability into the batch world using pure script - no compiled binaries are required.

One negative aspect of this utility is it is relatively slow.

The only other negative is PowerShell is not standard for XP. But XP is no longer supported by MicroSoft, so this should become less an less an issue over time.

Some of the nice features:

- Set Screen size independent of Buffer size
- Set color attributes of future output without changing color of existing screen content
- Reposition the cursor anywhere within the current buffer area.

Code: Select all

@echo off
:::console.bat  [option=value|/Switch]...
:::
:::  Utility for getting and/or setting various console window attributes.
:::
:::  Displays this help if no options are specified.
:::
:::  Options: Used to set console attribute values. Options are always
:::    processed in the order in which they appear.
:::
:::    WX={WindowWidthValue}
:::    WY={WindowHeightValue}
:::    BX={BufferWidthValue}
:::    BY={BufferHeightValue}
:::    CX={CursorPositionXCoordinate}
:::    CY={CursorPositionYCoordinate}
:::    CS={CursorSizeValue}
:::    BC={BackgroundColorValue}
:::    FC={ForegroundColorValue}
:::
:::  Switches: Always processed after all options, regardless of order.
:::
:::    /G - Get various console attributes and store the values in the
:::         following environment variables:
:::
:::           console.BufferSize.Height
:::           console.BufferSize.Width
:::           console.ColorBackground.Name
:::           console.ColorBackground.Num
:::           console.ColorForeground.Name
:::           console.ColorForeground.Num
:::           console.CursorPosition.X
:::           console.CursorPosition.Y
:::           console.CursorSize
:::           console.WindowMaxPhysicalSize.Height
:::           console.WindowMaxPhysicalSize.Width
:::           console.WindowMaxSize.Height
:::           console.WindowMaxSize.Width
:::           console.WindowPosition.X
:::           console.WindowPosition.Y
:::           console.WindowSize.Height
:::           console.WindowSize.Width
:::
:::    /D - Get the same console attributes described for /G but write the
:::         values to stdout instead of storing them in environment variables.
:::
:::    /D and /G can be combined to both store the values in environment
:::    variables and write the values to stdout.
:::
:::  console.bat version 1.0 was written by Dave Benham
:::

setlocal enableDelayedExpansion
for %%v in (att obj flag) do for /f "delims==" %%V in ('set %%v_ 2^>nul') do set "%%V="
set "obj_wx=WindowSize"
set "obj_wy=WindowSize"
set "obj_bx=BufferSize"
set "obj_by=BufferSize"
set "obj_cx=CursorPosition"
set "obj_cy=CursorPosition"
set "obj_cs=CursorSize"
set "obj_bc=BackgroundColor"
set "obj_fc=ForegroundColor"
set "att_wx=Width"
set "att_wy=Height"
set "att_bx=Width"
set "att_by=Height"
set "att_cx=X"
set "att_cy=Y"
set "cmd="
set "get="
set "var="
set "show="
set /a Black=0, DarkBlue=1, DarkGreen=2, DarkCyan=3, DarkRed=4, DarkMagenta=5, DarkYellow=6, Gray=7, DarkGray=8, Blue=9, Green=10, Cyan=11, Red=12, Magenta=13, Yellow=14, White=15

:parse
if "%~1"=="" goto :go
if not defined cmd set "cmd=$U=$Host.ui.rawui;"
if /i "%~1"=="/G" (
  set /a get=var=1
) else if /i "%~1"=="/D" (
  set /a get=show=1
) else if defined att_%~1 (
  if not defined flag_!obj_%~1! (
    set flag_!obj_%~1!=1
    set "cmd=!cmd!$!obj_%~1!=$U.!obj_%~1!;"
  )
  set "cmd=!cmd!$!obj_%~1!.!att_%~1!=%~2;$U.!obj_%~1!=$!obj_%~1!;"
  shift /1
) else (
  set "cmd=!cmd!$U.!obj_%~1!=%~2;"
)
shift /1
goto :parse

:go
if defined get set "cmd=!cmd!write-host($U.WindowSize,$U.BufferSize,$U.WindowPosition,$U.MaxWindowSize,$U.MaxPhysicalWindowSize,$U.CursorPosition,$U.CursorSize,$U.BackgroundColor,$U.ForegroundColor);"

if not defined cmd (
  for /f "tokens=* delims=:" %%A in ('findstr "^:::" "%~f0"') do echo(%%A
) else for /f "tokens=1-15 delims=, " %%A in (
 'powershell -command "&{%cmd%}"'
) do for /f "tokens=1,2" %%P in ("!%%N! !%%O!") do (
  if defined var endlocal
  set /a console.WindowSize.Width=%%A,^
         console.WindowSize.Height=%%B,^
         console.BufferSize.Width=%%C,^
         console.BufferSize.Height=%%D,^
         console.WindowPosition.X=%%E,^
         console.WindowPosition.Y=%%F,^
         console.WindowMaxSize.Width=%%G,^
         console.WindowMaxSize.Height=%%H,^
         console.WindowMaxPhysicalSize.Width=%%I,^
         console.WindowMaxPhysicalSize.Height=%%J,^
         console.CursorPosition.X=%%K,^
         console.CursorPosition.Y=%%L,^
         console.CursorSize=%%M,^
         console.ColorBackground.Num=%%P,^
         console.ColorForeground.Num=%%Q
  set "console.ColorBackground.Name=%%N"
  set "console.ColorForeground.Name=%%O"
  if "%show%"=="1" set console
)


Dave Benham
Last edited by dbenham on 14 May 2016 13:07, edited 3 times in total.

ShadowThief
Expert
Posts: 1160
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: CONSOLE.BAT - Get and set console window attributes via hybrid batch/powershell

#2 Post by ShadowThief » 30 Mar 2016 20:33

dbenham wrote: - Reposition the cursor anywhere within the current buffer area.


oh boy oh boy oh boy oh boy oh boy oh boy oh boy oh boy oh boy oh boy oh boy oh boy oh boy oh boy oh boy

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: CONSOLE.BAT - Get and set console window attributes via hybrid batch/powershell

#3 Post by dbenham » 28 Apr 2016 21:35

Here is version 2.0, with the following enhancements:

1) Major performance improvement by launching a continuously running PowerShell process in parallel to service requests.

2) Added output options to write strings directly to the console, with or without terminating newline. This enables construction of multi-color lines with a single call to CONSOLE.

3) Added options to set the window position, which is the upper left corner of the displayed window relative to the overall buffer space.

Usage notes:

The first CALL to console.bat with at least one option automatically launches the PowerShell parallel process. The process is launched using the START command with the /B option. It takes time for the PowerShell process to initialize before it is ready to process commands. For best initialization performance, the initial CONSOLE call should be made early in your batch script, with only the /START option. This call will return almost immediately, so your script can continue its initialization while the PowerShell process completes its initialization in parallel.

The initial call also defines critical config_* environment variables that are passed back to the calling script. These config_* variables must remain defined until you /STOP the process. So the initial call cannot be made within a FOR /F IN() clause, or on either side of a pipe, or as part of a CMD or START command.

A call to CONSOLE does not return until all options have been processed by the PowerShell process.

The PowerShell console process should be killed via the /STOP option as soon as you no longer need CONSOLE commands. A window with a running PowerShell console process cannot be programmatically closed until the PowerShell process is killed. But you can always kill the window by manually closing the window.

CONSOLE.BAT can be run simultaneously in multiple windows. CONSOLE.BAT uses lock files to detect collisions, and makes sure that each instantiation is given its own unique temporary file names for inter-process communication. The temporary lock file with a name like "console.hh.mm.ss.lock.n" will remain locked as long as the PowerShell process is still running. Any attempt to delete the file will fail if the PowerShell is still running. You can use this fact to determine if PowerShell is still running - simply try to delete the lock file: if you succeed, then PowerShell is not running, so you can safely delete the associated cmd and out temporary files. However, you generally should not have to worry about that. A properly closed CONSOLE session will automatically delete temporary files. Aborted sessions (the result of manual closure of the window) will automatically be cleaned up the next time CONSOLE is run.

The PowerShell process is in a continuously running polling loop, looking for commands to execute. It sleeps between each loop iteration, so as not to abuse system resources. The default polling interval sleep time is 10 msec. You can use the /PI option to use a different value. Small numbers improve responsiveness, but utilize more system resources.

So here is the code :)

CONSOLE.BAT version 2.0

Code: Select all

@echo off
goto :start
:::console  [/option[=value]] ...
:::
:::  Utility for manipulating the console window within a batch script.
:::  This utility works by launching a parallel PowerShell process within the
:::  same window to service requests in a timely fashion. The initial call also
:::  defines a series of environment variables with names beginning with console_
:::  that must be preserved until the PowerShell process is stopped.
:::
:::  Options are generally processed from left to right.
:::
:::  A call without options displays this help.
:::
:::  Admin Options: Used to start and stop the PowerShell process.
:::
:::    /START - Start the PowerShell process. Only needed if the first call
:::             to console.bat does not have any other options.
:::
:::    /STOP  - Stop the PowerShell process immediately.
:::
:::  Output Options: Used to write strings directly to the console (not stdout).
:::
:::      Note: Quoted string literals require the following escape sequences:
:::        " -> ""
:::        ! -> ^!  (or ^^! if delayed expansion is enabled)
:::        ^ -> ^^  (or ^^^^ if delayed expansion is enabled)
:::
:::    /WS="{String}"      - Write a string literal, without a newline.
:::
:::    /WV={VariableName}  - Write a variable, without a newline.
:::
:::    /WSN="{String}"     - Write a string literal, terminated by a newline.
:::
:::    /WVN={VariableName} - Write a variable, terminated by a newline
:::
:::  Set Options: Used to set console attributes.
:::
:::    /BW={BufferWidth}
:::    /BH={BufferHeight}
:::    /WW={WindowWidth}
:::    /WH={WindowHeight}
:::    /WX={WindowPositionX}
:::    /WY={WindowPositionY}
:::    /CX={CursorPositionX}
:::    /CY={CursorPositionY}
:::    /CS={CursorSize}       - integer from 0-100
:::    /BC={BackgroundColor}  - integer from 0-15 or color name
:::    /FC={ForegroundColor}  - integer from 0-15 or color name
:::    /PI={PollingInterval}  - in msec, initial value=10, continuous=0
:::
:::  Get Options: Used to retrieve console attributes. Get options are always
:::    processed after all other options, regardless of order. Theses options
:::    cannot be combined with /STOP.
:::
:::    /G - Get various console attributes and store the values in the
:::         following environment variables:
:::
:::           console.BufferSize.Height
:::           console.BufferSize.Width
:::           console.ColorBackground.Name
:::           console.ColorBackground.Num
:::           console.ColorForeground.Name
:::           console.ColorForeground.Num
:::           console.CursorPosition.X
:::           console.CursorPosition.Y
:::           console.CursorSize
:::           console.PollingInterval
:::           console.WindowMaxPhysicalSize.Height
:::           console.WindowMaxPhysicalSize.Width
:::           console.WindowMaxSize.Height
:::           console.WindowMaxSize.Width
:::           console.WindowPosition.X
:::           console.WindowPosition.Y
:::           console.WindowSize.Height
:::           console.WindowSize.Width
:::
:::    /D - Get the same console attributes described for /G but write the
:::         values to stdout instead of storing them in environment variables.
:::
:::    /D and /G can be combined to both store the values in environment
:::    variables and write the values to stdout.
:::
:::  CONSOLE.BAT version 2.0 was written by Dave Benham
:::

:start
if "%~1"=="" (
  for /f "tokens=* delims=:" %%A in ('findstr "^:::" "%~f0"') do echo(%%A
  exit /b
)

if defined console_config.lockFile ((call ) 9>>"%console_config.lockFile%") 2>nul || goto :skipInit
call :init 2>nul
:skipInit

setlocal enableDelayedExpansion
set "console_cmd="
set "console_get="
set "console_var="
set "console_show="
set "console_write= /WS /WV /WSN /WVN "

:parse
if "%~1"=="" goto :go
if /i "%~1"=="/G" (
  set /a console_get=console_var=1
) else if /i "%~1"=="/D" (
  set /a console_get=console_show=1
) else if /i "%~1"=="/START" (
  (call )
) else if /i "%~1"=="/STOP" (
  set "console_cmd=!console_cmd!del $cmdFile;exit;"
  set "console_config.stop=1"
) else (
  if /i "%~1"=="/PI" (
    set "console_cmd=!console_cmd!$delay=%~2;"
  ) else if "!console_write: %~1 =!" neq "!console_write!" (
    set "console_test=%~1"
    if "!console_test:S=!" neq "!console_test!" (
      set "console_str=%~2"!
    ) else (
      set "console_str=!%~2!"
      if defined console_str (
        set "console_str=!console_str:"=""!"
      )
    )
    if defined console_str (
      set "console_str=!console_str:`=``!"
      set "console_str=!console_str:$=`$!"
      set "console_cmd=!console_cmd!write-host "!console_str!""
      if "!console_test:N=!" equ "!console_test!" (
        set "console_cmd=!console_cmd! -noNewLine;"
      ) else set "console_cmd=!console_cmd!;"
    ) else if /i "%~1" == "/WVN" set "console_cmd=!console_cmd!write-host $empty;"
  ) else if defined console_obj_%~1 (
    set "console_cmd=!console_cmd!$O=$U.!console_obj_%~1!;$O.!console_att_%~1!=%~2;$U.!console_obj_%~1!=$O;"
  ) else if defined console_att_%~1 (
    set "console_cmd=!console_cmd!$U.!console_att_%~1!="%~2";"
  ) else (
    >&2 echo Invalid option: %~1
    exit /b 1
  )
  if "%~2" == "" (
    >&2 echo Missing value for option %~1
    exit /b 1
  )
  shift /1
)
shift /1
goto :parse

:go
if defined console_get (
  set console_cmd=!console_cmd!"$($U.WindowSize) $($U.BufferSize) $($U.WindowPosition) $($U.MaxWindowSize) $($U.MaxPhysicalWindowSize) $($U.CursorPosition) $($U.CursorSize) $($U.BackgroundColor) $($U.ForegroundColor) $($delay)";
)

if not defined console_cmd exit /b
echo(!console_cmd! >"%console_config.cmdFile%"
:wait
if exist "%console_config.cmdFile%" goto :wait
(for /f "usebackq tokens=1-16 delims=, " %%A in (
  "%console_config.outFile%"
) do for /f "tokens=1,2" %%Q in ("!console_color.%%N! !console_color.%%O!") do (
  if defined console_var endlocal&set "console_config.stop=%console_config.stop%"
  set /a console.WindowSize.Width=%%A,^
         console.WindowSize.Height=%%B,^
         console.BufferSize.Width=%%C,^
         console.BufferSize.Height=%%D,^
         console.WindowPosition.X=%%E,^
         console.WindowPosition.Y=%%F,^
         console.WindowMaxSize.Width=%%G,^
         console.WindowMaxSize.Height=%%H,^
         console.WindowMaxPhysicalSize.Width=%%I,^
         console.WindowMaxPhysicalSize.Height=%%J,^
         console.CursorPosition.X=%%K,^
         console.CursorPosition.Y=%%L,^
         console.CursorSize=%%M,^
         console.PollingInterval=%%P,^
         console.ColorBackground.Num=%%Q,^
         console.ColorForeground.Num=%%R
  set "console.ColorBackground.Name=%%N"
  set "console.ColorForeground.Name=%%O"
  if "%console_show%"=="1" set console.
)) 2>nul
:stop
if defined console_config.stop (
  del "%console_config.outFile%" 2>nul >nul
  del "%console_config.lockFile%" 2>nul >nul
  if exist "%console_config.lockFile%" goto :stop
)
exit /b 0

:init

:: Clean up dead sessions
for %%F in ("%temp%\console.??.??.*.lock.???") do (
  del "%%F"
  if not exist "%%F" for %%G in ("%%~dpnF") do del "%%~dpnG.*%%~xF"
) >nul

for %%v in (console_ color.) do for /f "delims==" %%V in ('set %%v 2^>nul') do set "%%V="
set "console_obj_/ww=WindowSize"
set "console_obj_/wh=WindowSize"
set "console_obj_/wx=WindowPosition"
set "console_obj_/wy=WindowPosition"
set "console_obj_/bw=BufferSize"
set "console_obj_/bh=BufferSize"
set "console_obj_/cx=CursorPosition"
set "console_obj_/cy=CursorPosition"
set "console_att_/cs=CursorSize"
set "console_att_/bc=BackgroundColor"
set "console_att_/fc=ForegroundColor"
set "console_att_/ww=Width"
set "console_att_/wh=Height"
set "console_att_/wx=X"
set "console_att_/wy=Y"
set "console_att_/bw=Width"
set "console_att_/bh=Height"
set "console_att_/cx=X"
set "console_att_/cy=Y"
set "console_config.base=%temp%\console.%time::=.%"
set "console_config.seq=1"
set /a console_color.Black=0,console_color.DarkBlue=1,console_color.DarkGreen=2,^
       console_color.DarkCyan=3,console_color.DarkRed=4,console_color.DarkMagenta=5,^
       console_color.DarkYellow=6,console_color.Gray=7,console_color.DarkGray=8,^
       console_color.Blue=9,console_color.Green=10,console_color.Cyan=11,^
       console_color.Red=12,console_color.Magenta=13,console_color.Yellow=14,^
       console_color.White=15

for /f "delims=.= tokens=1-3" %%A in ('set console_color.') do set "%%A.%%C=%%B"

:retry
set "console_config.cmdFile=%console_config.base%.cmd.%console_config.seq%"
set "console_config.outFile=%console_config.base%.out.%console_config.seq%"
set "console_config.lockFile=%console_config.base%.lock.%console_config.seq%"

setlocal
set "console_config.cmdFile=%console_config.cmdFile:`=``%"
set "console_config.cmdFile=%console_config.cmdFile:$=`$%"
set "console_config.outFile=%console_config.outFile:`=``%"
set "console_config.outFile=%console_config.outFile:$=`$%"

start "" /b powershell -command ^
$empty="""""""";^
$delay=10;^
$cmdFile=""""%console_config.cmdFile%"""";^
$outFile=""""%console_config.outFile%"""";^
$U=$Host.ui.rawui;^
while (1){^
  if (test-path $cmdFile){^
    $cmd=gc $cmdFile;^
    iex $cmd ^| out-file $outFile -width 100 -encoding default;^
    del $cmdFile;^
  };^
  sleep -m $delay;^
} 9>"%console_config.lockFile%" || (
  endlocal
  set /a console_config.seq+=1
  goto :retry
)

endlocal
exit /b


Dave Benham

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: CONSOLE.BAT - Get and set console window attributes via hybrid batch/powershell

#4 Post by sambul35 » 28 Apr 2016 23:08

Is it possible to set only console height and width in a very short 1-2 line code that can be added to a batch that is run by Windows Task Scheduler, or controlled by batch arguments?

Also, is there a way to minimize batch window from within the batch once it started or by starting it with certain argument, without using a 2nd batch for that?

ShadowThief
Expert
Posts: 1160
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: CONSOLE.BAT - Get and set console window attributes via hybrid batch/powershell

#5 Post by ShadowThief » 29 Apr 2016 02:52

sambul35 wrote:Is it possible to set only console height and width in a very short 1-2 line code that can be added to a batch that is run by Windows Task Scheduler

At the risk of sounding like a wiseass, why not just use mode con for that?

sambul35
Posts: 192
Joined: 18 Jan 2012 10:13

Re: CONSOLE.BAT - Get and set console window attributes via hybrid batch/powershell

#6 Post by sambul35 » 29 Apr 2016 06:26

Good suggestion for dummies like me. :D Useful in this thread too.

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: CONSOLE.BAT - Get and set console window attributes via hybrid batch/powershell

#7 Post by dbenham » 13 May 2016 04:35

Here is version 2.1:

- Fixed a /WS and /WSN bug where some string literals were causing fatal batch syntax errors.
- Added /S sleep option to help with smooth animation

After the code are a couple example scripts that demonstrate the new features.

Code: Select all

@echo off
goto :console

::CONSOLE.BAT version 2.1 by Dave Benham
::
::  Release History:
::    2.1  2016-05-13: Added /S option to sleep for N msec
::                     Bug fix - syntax error parsing some string literals
::    2.0  2016-04-28: Major rewrite
::                     - Speed improved by launching parallel process
::                     - Option syntax reworked
::                     - Added options for writing strings to the console
::                     - Added option to set the window position relative
::                       to the buffer space
::    1.0  2016-03-30: Initial release - slow due to PowerShell startup time
::
:: ========================= DOCUMENTATION ==========================
:::
:::console  [/option[=value]] ...
:::
:::  Utility for manipulating the console window within a batch script.
:::  This utility works by launching a parallel PowerShell process within the
:::  same window to service requests in a timely fashion. The initial call also
:::  defines a series of environment variables with names beginning with console_
:::  that must be preserved until the PowerShell process is stopped.
:::
:::  Options are generally processed from left to right.
:::
:::  A call without options displays this help.
:::
:::  Admin Options: Used to start and stop the PowerShell process.
:::
:::    /START - Start the PowerShell process. Only needed if the first call
:::             to console.bat does not have any other options.
:::
:::    /STOP  - Stop the PowerShell process immediately.
:::
:::  Output Options: Used to write strings directly to the console (not stdout).
:::
:::      Note: Quoted string literals require the following escape sequences:
:::        " -> ""
:::        ! -> ^!  (or ^^! if delayed expansion is enabled)
:::        ^ -> ^^  (or ^^^^ if delayed expansion is enabled)
:::
:::    /WS="{String}"      - Write a string literal, without a newline.
:::
:::    /WV={VariableName}  - Write a variable, without a newline.
:::
:::    /WSN="{String}"     - Write a string literal, terminated by a newline.
:::
:::    /WVN={VariableName} - Write a variable, terminated by a newline
:::
:::  Set Options: Used to set console attributes.
:::
:::    /BW={BufferWidth}
:::    /BH={BufferHeight}
:::    /WW={WindowWidth}
:::    /WH={WindowHeight}
:::    /WX={WindowPositionX}
:::    /WY={WindowPositionY}
:::    /CX={CursorPositionX}
:::    /CY={CursorPositionY}
:::    /CS={CursorSize}       - integer from 0-100
:::    /BC={BackgroundColor}  - integer from 0-15 or color name
:::    /FC={ForegroundColor}  - integer from 0-15 or color name
:::    /PI={PollingInterval}  - in msec, initial value=10, continuous=0
:::
:::  Get Options: Used to retrieve console attributes. Get options are always
:::    processed after all other options, regardless of order. Theses options
:::    cannot be combined with /STOP.
:::
:::    /G - Get various console attributes and store the values in the
:::         following environment variables:
:::
:::           console.BufferSize.Height
:::           console.BufferSize.Width
:::           console.ColorBackground.Name
:::           console.ColorBackground.Num
:::           console.ColorForeground.Name
:::           console.ColorForeground.Num
:::           console.CursorPosition.X
:::           console.CursorPosition.Y
:::           console.CursorSize
:::           console.PollingInterval
:::           console.WindowMaxPhysicalSize.Height
:::           console.WindowMaxPhysicalSize.Width
:::           console.WindowMaxSize.Height
:::           console.WindowMaxSize.Width
:::           console.WindowPosition.X
:::           console.WindowPosition.Y
:::           console.WindowSize.Height
:::           console.WindowSize.Width
:::
:::    /D - Get the same console attributes described for /G but write the
:::         values to stdout instead of storing them in environment variables.
:::
:::    /D and /G can be combined to both store the values in environment
:::    variables and write the values to stdout.
:::
:::  Miscellaneous:
:::
:::    /S={msec} - Sleep for the specified number of msec. Note that there will
:::                be additional delay for batch parsing, plus as much as the
:::                polling interval delay for PowerShell to receive the command.
:::
:::  CONSOLE.BAT version 2.1 was written by Dave Benham
:::

:console
if "%~1"=="" (
  for /f "tokens=* delims=:" %%A in ('findstr "^:::" "%~f0"') do echo(%%A
  exit /b
)

if defined console_config.lockFile ((call ) 9>>"%console_config.lockFile%") 2>nul || goto :skipInit
call :init 2>nul
:skipInit

setlocal enableDelayedExpansion
set "console_cmd="
set "console_get="
set "console_var="
set "console_show="
set "console_write= /WS /WV /WSN /WVN "

:parse
if "%~1"=="" goto :go
if /i "%~1"=="/G" (
  set /a console_get=console_var=1
) else if /i "%~1"=="/D" (
  set /a console_get=console_show=1
) else if /i "%~1"=="/START" (
  (call )
) else if /i "%~1"=="/STOP" (
  set "console_cmd=!console_cmd!del $cmdFile;exit;"
  set "console_config.stop=1"
) else (
  if "%~2" == "" (
    >&2 echo Missing value for option %~1
    exit /b 1
  )
  if /i "%~1"=="/PI" (
    set "console_cmd=!console_cmd!$delay=%~2;"
  ) else if /i "%~1"=="/S" (
    set "console_cmd=!console_cmd!sleep -m %~2;"
  ) else if "!console_write: %~1 =!" neq "!console_write!" (
    set "console_test=%~1"
    if "!console_test:S=!" neq "!console_test!" (
      set "console_str=%~2"!
    ) else (
      set "console_str=!%~2!"
      if defined console_str (
        set "console_str=!console_str:"=""!"
      )
    )
    if defined console_str (
      set "console_str=!console_str:`=``!"
      set "console_str=!console_str:$=`$!"
      set "console_cmd=!console_cmd!write-host "!console_str!""
      if "!console_test:N=!" equ "!console_test!" (
        set "console_cmd=!console_cmd! -noNewLine;"
      ) else set "console_cmd=!console_cmd!;"
    ) else if /i "%~1" == "/WVN" set "console_cmd=!console_cmd!write-host $empty;"
  ) else if defined console_obj_%~1 (
    set "console_cmd=!console_cmd!$O=$U.!console_obj_%~1!;$O.!console_att_%~1!=%~2;$U.!console_obj_%~1!=$O;"
  ) else if defined console_att_%~1 (
    set ^"console_cmd=!console_cmd!$U.!console_att_%~1!="%~2";"
  ) else (
    >&2 echo Invalid option: %~1
    exit /b 1
  )
  shift /1
)
shift /1
goto :parse

:go
if defined console_get (
  set console_cmd=!console_cmd!"$($U.WindowSize) $($U.BufferSize) $($U.WindowPosition) $($U.MaxWindowSize) $($U.MaxPhysicalWindowSize) $($U.CursorPosition) $($U.CursorSize) $($U.BackgroundColor) $($U.ForegroundColor) $($delay)";
)

if not defined console_cmd exit /b
echo(!console_cmd! >"%console_config.cmdFile%"
:wait
if exist "%console_config.cmdFile%" goto :wait
(for /f "usebackq tokens=1-16 delims=, " %%A in (
  "%console_config.outFile%"
) do for /f "tokens=1,2" %%Q in ("!console_color.%%N! !console_color.%%O!") do (
  if defined console_var endlocal&set "console_config.stop=%console_config.stop%"
  set /a console.WindowSize.Width=%%A,^
         console.WindowSize.Height=%%B,^
         console.BufferSize.Width=%%C,^
         console.BufferSize.Height=%%D,^
         console.WindowPosition.X=%%E,^
         console.WindowPosition.Y=%%F,^
         console.WindowMaxSize.Width=%%G,^
         console.WindowMaxSize.Height=%%H,^
         console.WindowMaxPhysicalSize.Width=%%I,^
         console.WindowMaxPhysicalSize.Height=%%J,^
         console.CursorPosition.X=%%K,^
         console.CursorPosition.Y=%%L,^
         console.CursorSize=%%M,^
         console.PollingInterval=%%P,^
         console.ColorBackground.Num=%%Q,^
         console.ColorForeground.Num=%%R
  set "console.ColorBackground.Name=%%N"
  set "console.ColorForeground.Name=%%O"
  if "%console_show%"=="1" set console.
)) 2>nul
:stop
if defined console_config.stop (
  del "%console_config.outFile%" 2>nul >nul
  del "%console_config.lockFile%" 2>nul >nul
  if exist "%console_config.lockFile%" goto :stop
)
exit /b 0

:init

:: Clean up dead sessions
for %%F in ("%temp%\console.??.??.*.lock.???") do (
  del "%%F"
  if not exist "%%F" for %%G in ("%%~dpnF") do del "%%~dpnG.*%%~xF"
) >nul

for %%v in (console_ color.) do for /f "delims==" %%V in ('set %%v 2^>nul') do set "%%V="
set "console_obj_/ww=WindowSize"
set "console_obj_/wh=WindowSize"
set "console_obj_/wx=WindowPosition"
set "console_obj_/wy=WindowPosition"
set "console_obj_/bw=BufferSize"
set "console_obj_/bh=BufferSize"
set "console_obj_/cx=CursorPosition"
set "console_obj_/cy=CursorPosition"
set "console_att_/cs=CursorSize"
set "console_att_/bc=BackgroundColor"
set "console_att_/fc=ForegroundColor"
set "console_att_/ww=Width"
set "console_att_/wh=Height"
set "console_att_/wx=X"
set "console_att_/wy=Y"
set "console_att_/bw=Width"
set "console_att_/bh=Height"
set "console_att_/cx=X"
set "console_att_/cy=Y"
set "console_config.base=%temp%\console.%time::=.%"
set "console_config.seq=1"
set /a console_color.Black=0,console_color.DarkBlue=1,console_color.DarkGreen=2,^
       console_color.DarkCyan=3,console_color.DarkRed=4,console_color.DarkMagenta=5,^
       console_color.DarkYellow=6,console_color.Gray=7,console_color.DarkGray=8,^
       console_color.Blue=9,console_color.Green=10,console_color.Cyan=11,^
       console_color.Red=12,console_color.Magenta=13,console_color.Yellow=14,^
       console_color.White=15

for /f "delims=.= tokens=1-3" %%A in ('set console_color.') do set "%%A.%%C=%%B"

:retry
set "console_config.cmdFile=%console_config.base%.cmd.%console_config.seq%"
set "console_config.outFile=%console_config.base%.out.%console_config.seq%"
set "console_config.lockFile=%console_config.base%.lock.%console_config.seq%"

setlocal
set "console_config.cmdFile=%console_config.cmdFile:`=``%"
set "console_config.cmdFile=%console_config.cmdFile:$=`$%"
set "console_config.outFile=%console_config.outFile:`=``%"
set "console_config.outFile=%console_config.outFile:$=`$%"

start "" /b powershell -command ^
$empty="""""""";^
$delay=10;^
$cmdFile=""""%console_config.cmdFile%"""";^
$outFile=""""%console_config.outFile%"""";^
$U=$Host.ui.rawui;^
while (1){^
  if (test-path $cmdFile){^
    $cmd=gc $cmdFile;^
    iex $cmd ^| out-file $outFile -width 100 -encoding default;^
    del $cmdFile;^
  };^
  sleep -m $delay;^
} 9>"%console_config.lockFile%" || (
  endlocal
  set /a console_config.seq+=1
  goto :retry
)

endlocal
exit /b


Here is a color output demo that I adapted from a StackOverflow post that used the FINDSTR color output method. This version using CONSOLE.BAT is much faster. The ASCII art was originally developed by Joan Stark. Her web page is no longer available, but a 2009 mirror is currently available at http://www.oocities.org/spunk1111/indexjava.htm.

Code: Select all

@echo off
:: Original ASCII art by Joan Stark
setlocal disableDelayedExpansion
call console /g
set "setColor=1"
if %console.colorForeground.num% == 15 if %console.colorBackground.num% == 0 set "setColor="
if defined setColor color 0F
echo(
echo(
call console ^
 /fc 14 /wsn "                ,      .-;"^
 /fc 14 /wsn "             ,  |\    / /  __,"^
 /fc 14 /wsn "             |\ '.`-.|  |.'.-'"^
 /fc 14 /wsn "              \`'-:  `; : /"^
 /fc 14 /wsn "               `-._'.  \'|"^
 /fc 14 /wsn "              ,_.-=` ` `  ~,_"^
 /fc 14 /ws "               '--,.    " /fc 12 /ws ".-. " /fc 14 /wsn ",=""."^
 /fc 14 /ws "                 /     " /fc 12 /ws "{ " /fc 10 /ws "* " /fc 12 /ws ")" /fc 14 /ws "`" /fc 6 /ws ";-." /fc 14 /wsn "}"^
 /fc 14 /ws "                 |      " /fc 12 /ws "'-' " /fc 6 /wsn "/__ |"^
 /fc 14 /ws "                 /          " /fc 6 /wsn "\_,\|"^
 /fc 14 /wsn "                 |          ("^
 /fc 14 /ws "             " /fc 12 /ws "__ " /fc 14 /wsn "/ '          \"^
 /fc 2 /ws "     /\_    " /fc 12 /ws "/,'`" /fc 14 /ws "|     '   " /fc 12 /wsn ".-~""~~-."^
 /fc 2 /ws "     |`.\_ " /fc 12 /ws "|   " /fc 14 /ws "/  ' ,    " /fc 12 /wsn "/        \"^
 /fc 2 /ws "   _/  `, \" /fc 12 /ws "|  " /fc 14 /ws "; ,     . " /fc 12 /wsn "|  ,  '  . |"^
 /fc 2 /ws "   \   `,  " /fc 12 /ws "|  " /fc 14 /ws "|  ,  ,   " /fc 12 /wsn "|  :  ;  : |"^
 /fc 2 /ws "   _\  `,  " /fc 12 /ws "\  " /fc 14 /ws "|.     ,  " /fc 12 /wsn "|  |  |  | |"^
 /fc 2 /ws "   \`  `.   " /fc 12 /ws "\ " /fc 14 /ws "|   '     " /fc 10 /ws "|" /fc 12 /wsn "\_|-'|_,'\|"^
 /fc 2 /ws "   _\   `,   " /fc 10 /ws "`" /fc 14 /ws "\  '  . ' " /fc 10 /ws "| |  | |  |           " /fc 2 /wsn "__"^
 /fc 2 /ws "   \     `,   " /fc 14 /ws "| ,  '    " /fc 10 /ws "|_/'-|_\_/     " /fc 2 /wsn "__ ,-;` /"^
 /fc 2 /ws "    \    `,    " /fc 14 /ws "\ .  , ' .| | | | |   " /fc 2 /wsn "_/' ` _=`|"^
 /fc 2 /ws "     `\    `,   " /fc 14 /ws "\     ,  | | | | |" /fc 2 /wsn "_/'   .=""  /"^
 /fc 2 /ws "     \`     `,   " /fc 14 /ws "`\      \/|,| ;" /fc 2 /wsn "/'   .=""    |"^
 /fc 2 /ws "      \      `,    " /fc 14 /ws "`\' ,  | ; " /fc 2 /wsn "/'    =""    _/"^
 /fc 2 /ws "       `\     `,  " /fc 5 /ws ".-""""-. " /fc 14 /ws "': " /fc 2 /wsn "/'    =""     /"^
 /fc 2 /ws "    jgs _`\    ;" /fc 5 /ws "_{  '   ; " /fc 2 /wsn "/'    =""      /"^
 /fc 2 /ws "       _\`-/__" /fc 5 /ws ".~  `." /fc 7 /ws "8" /fc 5 /ws ".'.""`~-. " /fc 2 /wsn "=""     _,/"^
 /fc 2 /ws "    __\      " /fc 5 /ws "{   '-." /fc 7 /ws "|" /fc 5 /ws ".'.--~'`}" /fc 2 /wsn "    _/"^
 /fc 2 /ws "    \    .=""` " /fc 5 /ws "}.-~""'" /fc 13 /ws "u" /fc 5 /ws "'-. '-..'  " /fc 2 /wsn "__/"^
 /fc 2 /ws "   _/  .""    " /fc 5 /ws "{  -'.~('-._,.'" /fc 2 /wsn "\_,/"^
 /fc 2 /ws "  /  .""    _/'" /fc 5 /wsn "`--; ;  `.  ;"^
 /fc 2 /ws "   .=""  _/'      " /fc 5 /wsn "`-..__,-'"^
 /fc 2 /ws "    __/'"^
 /fc 15 /stop
echo(
echo(

And here is a simple color animation of a classic New Years eve blowout party favor:

Code: Select all

@echo off
setlocal enableDelayedExpansion
set "delay=%~1"
set /a delay=delay
if %delay% == 0 set /a delay=50
call console /g
set "setColor=1"
if %console.colorForeground.num% == 15 if %console.colorBackground.num% == 0 set "setColor="
if defined setColor color 0F

set "S0=/"
set "S1=-"
set "S2=\"
set "S3=|"
set ^"cmd1=/s 1000"
for /l %%N in (4 1 21) do (
  set /a "s=%%N%%4"
  for %%s in (!s!) do set "cmd1=!cmd1! /s %delay% /cx %%N /ws "_!S%%s!""
)
set "cmd2=/s 1000"
for /l %%N in (21 -1 4) do (
  set /a "s=(%%N-1)%%4"
  for %%s in (!s!) do set "cmd2=!cmd2! /s %delay% /cx %%N /ws "!S%%s! ""
)
cls
echo(
call console /cs 0 /bc red /ws "    " /bc black /fc yellow /ws "|"
call console %cmd1%
call console %cmd2%
call console %cmd1%
call console %cmd2% /fc white /cs 25 /stop
echo(


Dave Benham

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: CONSOLE.BAT - Get and set console window attributes via hybrid batch/powershell

#8 Post by dbenham » 14 May 2016 13:06

Version 2.2

Added the ability to set size and position relative to current values.

After the code is a simple yo-yo animation script that demonstrates use of the new feature.

CONSOLE.BAT v2.2

Code: Select all

@echo off
goto :console

::CONSOLE.BAT version 2.2 by Dave Benham
::
::  Release History:
::    2.2  2016-05-14: Added ability to set attributes relative to current value
::    2.1  2016-05-13: Added /S option to sleep for N msec
::                     Bug fix - syntax error parsing some string literals
::    2.0  2016-04-28: Major rewrite
::                     - Speed improved by launching parallel process
::                     - Option syntax reworked
::                     - Added options for writing strings to the console
::                     - Added option to set the window position relative
::                       to the buffer space
::    1.0  2016-03-30: Initial release - slow due to PowerShell startup time
::
:: ========================= DOCUMENTATION ==========================
:::
:::console  [/option[=value]] ...
:::
:::  Utility for manipulating the console window within a batch script.
:::  This utility works by launching a parallel PowerShell process within the
:::  same window to service requests in a timely fashion. The initial call also
:::  defines a series of environment variables with names beginning with console_
:::  that must be preserved until the PowerShell process is stopped.
:::
:::  Options are generally processed from left to right.
:::
:::  A call without options displays this help.
:::
:::  Admin Options: Used to start and stop the PowerShell process.
:::
:::    /START - Start the PowerShell process. Only needed if the first call
:::             to console.bat does not have any other options.
:::
:::    /STOP  - Stop the PowerShell process immediately.
:::
:::  Output Options: Used to write strings directly to the console (not stdout).
:::
:::      Note: Quoted string literals require the following escape sequences:
:::        " -> ""
:::        ! -> ^!  (or ^^! if delayed expansion is enabled)
:::        ^ -> ^^  (or ^^^^ if delayed expansion is enabled)
:::
:::    /WS="{String}"      - Write a string literal, without a newline.
:::
:::    /WV={VariableName}  - Write a variable, without a newline.
:::
:::    /WSN="{String}"     - Write a string literal, terminated by a newline.
:::
:::    /WVN={VariableName} - Write a variable, terminated by a newline
:::
:::  Set Options: Used to set console attributes:
:::
:::    Without sign represents absolute value
:::    With + or - sign represents increase or decrease from current setting
:::      /BW=[+|-]{BufferWidth}
:::      /BH=[+|-]{BufferHeight}
:::      /WW=[+|-]{WindowWidth}
:::      /WH=[+|-]{WindowHeight}
:::      /WX=[+|-]{WindowPositionX}
:::      /WY=[+|-]{WindowPositionY}
:::      /CX=[+|-]{CursorPositionX}
:::      /CY=[+|-]{CursorPositionY}
:::
:::    Absolute values only
:::      /CS={CursorSize}       - integer from 0-100
:::      /BC={BackgroundColor}  - integer from 0-15 or color name
:::      /FC={ForegroundColor}  - integer from 0-15 or color name
:::      /PI={PollingInterval}  - in msec, initial value=10, continuous=0
:::
:::  Get Options: Used to retrieve console attributes. Get options are always
:::    processed after all other options, regardless of order. These options
:::    cannot be combined with /STOP.
:::
:::    /G - Get various console attributes and store the values in the
:::         following environment variables:
:::
:::           console.BufferSize.Height
:::           console.BufferSize.Width
:::           console.ColorBackground.Name
:::           console.ColorBackground.Num
:::           console.ColorForeground.Name
:::           console.ColorForeground.Num
:::           console.CursorPosition.X
:::           console.CursorPosition.Y
:::           console.CursorSize
:::           console.PollingInterval
:::           console.WindowMaxPhysicalSize.Height
:::           console.WindowMaxPhysicalSize.Width
:::           console.WindowMaxSize.Height
:::           console.WindowMaxSize.Width
:::           console.WindowPosition.X
:::           console.WindowPosition.Y
:::           console.WindowSize.Height
:::           console.WindowSize.Width
:::
:::    /D - Get the same console attributes described for /G but write the
:::         values to stdout instead of storing them in environment variables.
:::
:::    /D and /G can be combined to both store the values in environment
:::    variables and write the values to stdout.
:::
:::  Miscellaneous:
:::
:::    /S={msec} - Sleep for the specified number of msec. Note that there may
:::                be additional delay for batch parsing, plus as much as the
:::                polling interval delay for PowerShell to receive the command.
:::
:::  CONSOLE.BAT version 2.1 was written by Dave Benham
:::

:console
if "%~1"=="" (
  for /f "tokens=* delims=:" %%A in ('findstr "^:::" "%~f0"') do echo(%%A
  exit /b
)

if defined console_config.lockFile ((call ) 9>>"%console_config.lockFile%") 2>nul || goto :skipInit
call :init 2>nul
:skipInit

setlocal enableDelayedExpansion
set "console_cmd="
set "console_get="
set "console_var="
set "console_show="
set "console_write= /WS /WV /WSN /WVN "

:parse
if "%~1"=="" goto :go
if /i "%~1"=="/G" (
  set /a console_get=console_var=1
) else if /i "%~1"=="/D" (
  set /a console_get=console_show=1
) else if /i "%~1"=="/START" (
  (call )
) else if /i "%~1"=="/STOP" (
  set "console_cmd=!console_cmd!del $cmdFile;exit;"
  set "console_config.stop=1"
) else (
  if "%~2" == "" (
    >&2 echo Missing value for option %~1
    exit /b 1
  )
  if /i "%~1"=="/PI" (
    set "console_cmd=!console_cmd!$delay=%~2;"
  ) else if /i "%~1"=="/S" (
    set "console_cmd=!console_cmd!sleep -m %~2;"
  ) else if "!console_write: %~1 =!" neq "!console_write!" (
    set "console_test=%~1"
    if "!console_test:S=!" neq "!console_test!" (
      set "console_str=%~2"!
    ) else (
      set "console_str=!%~2!"
      if defined console_str (
        set "console_str=!console_str:"=""!"
      )
    )
    if defined console_str (
      set "console_str=!console_str:`=``!"
      set "console_str=!console_str:$=`$!"
      set "console_cmd=!console_cmd!write-host "!console_str!""
      if "!console_test:N=!" equ "!console_test!" (
        set "console_cmd=!console_cmd! -noNewLine;"
      ) else set "console_cmd=!console_cmd!;"
    ) else if /i "%~1" == "/WVN" set "console_cmd=!console_cmd!write-host $empty;"
  ) else if defined console_obj_%~1 (
    for /f "delims=+ tokens=1*" %%A in ("%~2") do if "%%A" neq "%~2" (
      set "console_cmd=!console_cmd!$O=$U.!console_obj_%~1!;$O.!console_att_%~1!+=%%A%%B;$U.!console_obj_%~1!=$O;"
    ) else for /f "delims=- tokens=1*" %%A in ("%~2") do if "%%A" neq "%~2" (
      set "console_cmd=!console_cmd!$O=$U.!console_obj_%~1!;$O.!console_att_%~1!-=%%A%%B;$U.!console_obj_%~1!=$O;"
    ) else (
      set "console_cmd=!console_cmd!$O=$U.!console_obj_%~1!;$O.!console_att_%~1!=%~2;$U.!console_obj_%~1!=$O;"
    )
  ) else if defined console_att_%~1 (
    set ^"console_cmd=!console_cmd!$U.!console_att_%~1!="%~2";"
  ) else (
    >&2 echo Invalid option: %~1
    exit /b 1
  )
  shift /1
)
shift /1
goto :parse

:go
if defined console_get (
  set console_cmd=!console_cmd!"$($U.WindowSize) $($U.BufferSize) $($U.WindowPosition) $($U.MaxWindowSize) $($U.MaxPhysicalWindowSize) $($U.CursorPosition) $($U.CursorSize) $($U.BackgroundColor) $($U.ForegroundColor) $($delay)";
)

if not defined console_cmd exit /b
echo(!console_cmd! >"%console_config.cmdFile%"
:wait
if exist "%console_config.cmdFile%" goto :wait
(for /f "usebackq tokens=1-16 delims=, " %%A in (
  "%console_config.outFile%"
) do for /f "tokens=1,2" %%Q in ("!console_color.%%N! !console_color.%%O!") do (
  if defined console_var endlocal&set "console_config.stop=%console_config.stop%"
  set /a console.WindowSize.Width=%%A,^
         console.WindowSize.Height=%%B,^
         console.BufferSize.Width=%%C,^
         console.BufferSize.Height=%%D,^
         console.WindowPosition.X=%%E,^
         console.WindowPosition.Y=%%F,^
         console.WindowMaxSize.Width=%%G,^
         console.WindowMaxSize.Height=%%H,^
         console.WindowMaxPhysicalSize.Width=%%I,^
         console.WindowMaxPhysicalSize.Height=%%J,^
         console.CursorPosition.X=%%K,^
         console.CursorPosition.Y=%%L,^
         console.CursorSize=%%M,^
         console.PollingInterval=%%P,^
         console.ColorBackground.Num=%%Q,^
         console.ColorForeground.Num=%%R
  set "console.ColorBackground.Name=%%N"
  set "console.ColorForeground.Name=%%O"
  if "%console_show%"=="1" set console.
)) 2>nul
:stop
if defined console_config.stop (
  del "%console_config.outFile%" 2>nul >nul
  del "%console_config.lockFile%" 2>nul >nul
  if exist "%console_config.lockFile%" goto :stop
)
exit /b 0

:init

:: Clean up dead sessions
for %%F in ("%temp%\console.??.??.*.lock.???") do (
  del "%%F"
  if not exist "%%F" for %%G in ("%%~dpnF") do del "%%~dpnG.*%%~xF"
) >nul

for %%v in (console_ color.) do for /f "delims==" %%V in ('set %%v 2^>nul') do set "%%V="
set "console_obj_/ww=WindowSize"
set "console_obj_/wh=WindowSize"
set "console_obj_/wx=WindowPosition"
set "console_obj_/wy=WindowPosition"
set "console_obj_/bw=BufferSize"
set "console_obj_/bh=BufferSize"
set "console_obj_/cx=CursorPosition"
set "console_obj_/cy=CursorPosition"
set "console_att_/cs=CursorSize"
set "console_att_/bc=BackgroundColor"
set "console_att_/fc=ForegroundColor"
set "console_att_/ww=Width"
set "console_att_/wh=Height"
set "console_att_/wx=X"
set "console_att_/wy=Y"
set "console_att_/bw=Width"
set "console_att_/bh=Height"
set "console_att_/cx=X"
set "console_att_/cy=Y"
set "console_config.base=%temp%\console.%time::=.%"
set "console_config.seq=1"
set /a console_color.Black=0,console_color.DarkBlue=1,console_color.DarkGreen=2,^
       console_color.DarkCyan=3,console_color.DarkRed=4,console_color.DarkMagenta=5,^
       console_color.DarkYellow=6,console_color.Gray=7,console_color.DarkGray=8,^
       console_color.Blue=9,console_color.Green=10,console_color.Cyan=11,^
       console_color.Red=12,console_color.Magenta=13,console_color.Yellow=14,^
       console_color.White=15

for /f "delims=.= tokens=1-3" %%A in ('set console_color.') do set "%%A.%%C=%%B"

:retry
set "console_config.cmdFile=%console_config.base%.cmd.%console_config.seq%"
set "console_config.outFile=%console_config.base%.out.%console_config.seq%"
set "console_config.lockFile=%console_config.base%.lock.%console_config.seq%"

setlocal
set "console_config.cmdFile=%console_config.cmdFile:`=``%"
set "console_config.cmdFile=%console_config.cmdFile:$=`$%"
set "console_config.outFile=%console_config.outFile:`=``%"
set "console_config.outFile=%console_config.outFile:$=`$%"

start "" /b powershell -command ^
$empty="""""""";^
$delay=10;^
$cmdFile=""""%console_config.cmdFile%"""";^
$outFile=""""%console_config.outFile%"""";^
$U=$Host.ui.rawui;^
while (1){^
  if (test-path $cmdFile){^
    $cmd=gc $cmdFile;^
    iex $cmd ^| out-file $outFile -width 100 -encoding default;^
    del $cmdFile;^
  };^
  sleep -m $delay;^
} 9>"%console_config.lockFile%" || (
  endlocal
  set /a console_config.seq+=1
  goto :retry
)

endlocal
exit /b


yoyo.bat

Code: Select all

@echo off
setlocal enableDelayedExpansion
set "delay=%~1"
set /a delay=delay
if %delay% == 0 set /a delay=50
call console /g
set "setColor=1"
if %console.colorForeground.num% == 15 if %console.colorBackground.num% == 0 set "setColor="
if defined setColor color 0F

set "cmd="
for /l %%N in (1 1 10) do set ^"cmd=!cmd! /s %delay% /cx -1 /ws "|" /cx -1 /cy +1 /ws "O"^"
for /l %%N in (1 1 10) do set ^"cmd=!cmd! /s %delay% /cx -1 /ws " " /cx -1 /cy -1 /ws "O"^"

cls
echo(
call console /cs 0 /fc yellow /ws "   YO-YO" /s 1000
for /l %%N in (1 1 4) do call console %cmd%
call console /fc white /cs %console.cursorSize% /stop
echo(


Dave Benham

npocmaka_
Posts: 512
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: CONSOLE.BAT - Get and set console window attributes via hybrid batch/powershell

#9 Post by npocmaka_ » 14 May 2016 15:04

With Add-Type cmdlet you can add also C# code. Unfortunately I don't think it will work well with batch/powershell hybrid (or just like this).

Do you think it will be possible?

This will allow to access the windows native apis more capabilities over the console (quick edit/insert mode, fonts , font size ..)

Aacini
Expert
Posts: 1885
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: CONSOLE.BAT - Get and set console window attributes via hybrid batch/powershell

#10 Post by Aacini » 14 May 2016 20:13

npocmaka_ wrote:With Add-Type cmdlet you can add also C# code. Unfortunately I don't think it will work well with batch/powershell hybrid (or just like this).

Do you think it will be possible?

This will allow to access the windows native apis more capabilities over the console (quick edit/insert mode, fonts , font size ..)


I used already the Add-Type cmdlet and -MemberDefinition (P/Invoke) mechanism (that does not require C# code) to call Win-32 API functions from PowerShell in my 2048.bat game; these functions are used to convert screen pixel coordinates of mouse clicks into row/col text window coordinates. This is the code segment of such definitions:

Code: Select all

   $GetConsoleWindow = Add-Type 'A' -PassThru -MemberDefinition '  ^
      [DllImport(\"Kernel32.dll\")]  ^
      public static extern int GetConsoleWindow();  ^
   ';  ^
   $GetClientRect,$RECT = Add-Type 'B' -PassThru -MemberDefinition '  ^
      [DllImport(\"user32.dll\")]  ^
      public static extern bool GetClientRect(IntPtr hWnd, ref RECT lpRect);  ^
      [StructLayout(LayoutKind.Sequential)]  ^
      public struct RECT { public int Left, Top, Right, Bottom; }  ^
   ';  ^
   $ScreenToClient,$POINT = Add-Type 'C' -PassThru -MemberDefinition '  ^
      [DllImport(\"user32.dll\")]  ^
      public static extern bool ScreenToClient(IntPtr hWnd, ref POINT lpPoint);  ^
      [StructLayout(LayoutKind.Sequential)]  ^
      public struct POINT { public int X, Y; }  ^
   ';  ^

I wrote this code based on this SO answer and the examples from Add-Type cmdlet help.

You may review the full 2048.bat game program here.

Antonio

Post Reply