Get the number of lines in cmd.exe window

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Get the number of lines in cmd.exe window

#1 Post by Aacini » 28 Mar 2016 11:48

In certain Batch files, that show an output on the whole screen (like games or graphics), it is required to know the number of lines on the screen because if the program show more lines, the screen contents scrolls and the output is distorted. The problem with the number of lines reported by MODE comand is that it refers to the screen buffer size, that usually is larger than the displayed window lines. A cumbersome solution to this problem had been to include a phrase like "remember that both the buffer and window sizes must be set to the same values" (like in this example); until now!

I discovered a method to correctly get the number of displayed lines in the cmd.exe window. Here it is:

Code: Select all

@if (@CodeSection == @Batch) @then


@echo off
setlocal

rem Get the number of *displayed* lines in the cmd.exe window
rem Antonio Perez Ayala

for /F "tokens=2 delims=:" %%a in ('mode con') do set /A "min=lastLines=0, max=%%a" & goto nextLine
:nextLine
   set /A "lines=(min+max)/2"
   cscript //nologo //E:JScript "%~F0" Q
   (for /L %%i in (1,1,%lines%) do @echo/) | more /E /C
   cscript //nologo //E:JScript "%~F0" q
   set /P "test="
   if %test% equ Q (
      set /A "min=lines+1"
      set /P "="
   ) else (
      set /a "max=lines-1"
   )
if %lines% neq %lastLines% set "lastLines=%lines%" & goto nextLine
set /A lines+=2
cls
echo Lines=%lines%
goto :EOF


@end


// JScript section
WScript.CreateObject("WScript.Shell").SendKeys(WScript.Arguments(0)+"{ENTER}");

This method may also be used to know the maximum number of lines that can be displayed on the screen. To do that, just set the buffer size to a high number with MODE command and then get the number of window lines. Tested on Windows 8.1

About the method used, as jeb would say: "is obvious" :wink:

Antonio
Last edited by Aacini on 29 Mar 2016 01:23, edited 1 time in total.

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Get the number of lines in cmd.exe window

#2 Post by aGerman » 28 Mar 2016 16:47

That's an interesting technique :)

I'm wondering if there was any advantage to prefer that technique over reading the related registry values?

Code: Select all

@echo off &setlocal
for /f "tokens=3" %%i in ('reg query "HKCU\Console" /v "ScreenBufferSize"') do set /a "sbh=%%i>>0x10, sbw=%%i&0xFFFF"
echo Screen Buffer Height %sbh%
echo Screen Buffer Width  %sbw%

for /f "tokens=3" %%i in ('reg query "HKCU\Console" /v "WindowSize"') do set /a "wh=%%i>>0x10, ww=%%i&0xFFFF"
echo Window Height %wh%
echo Window Width  %ww%

pause

It displays the same number of lines in my tests (Win7).

Regards
aGerman

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

Re: Get the number of lines in cmd.exe window

#3 Post by Aacini » 28 Mar 2016 19:19

aGerman wrote:That's an interesting technique :)

I'm wondering if there was any advantage to prefer that technique over reading the related registry values?
. . .
It displays the same number of lines in my tests (Win7).

Regards
aGerman


That method don't works here:

Code: Select all

C:\> mode

Estado para dispositivo CON:
----------------------------
    Líneas:              200
    Columnas:            80
    Ritmo del teclado:   31
    Retardo del teclado: 1
    Página de códigos:    850


C:\> "GetLines - aGerman.bat"
Screen Buffer Height 200
Screen Buffer Width  80
Window Height 50
Window Width  80

The real number of displayed lines on my screen is 39, that is correctly reported by my program.

Also, if I change the number of lines with MODE, your method still report the same number of lines:

Code: Select all

C:\> mode

Estado para dispositivo CON:
----------------------------
    Líneas:              25
    Columnas:            80
    Ritmo del teclado:   31
    Retardo del teclado: 1
    Página de códigos:    850


C:\> "GetLines - aGerman.bat"
Screen Buffer Height 200
Screen Buffer Width  80
Window Height 50
Window Width  80

Antonio

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Get the number of lines in cmd.exe window

#4 Post by foxidrive » 29 Mar 2016 00:35

It worked here too Antonio, cool.

I haven't looked at the code, it flashed a string of these on the screen if you need to know.

The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.

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

Re: Get the number of lines in cmd.exe window

#5 Post by Aacini » 29 Mar 2016 01:33

foxidrive wrote:It worked here too Antonio, cool.

I haven't looked at the code, it flashed a string of these on the screen if you need to know.

The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
. . .
The process tried to write to a nonexistent pipe.


This is strange. I just tested it on Win 8.1 and worked ok, but when I tested it on Win-XP I got the same "nonexistent pipe" error messages. I changed the "(for ...) | more" line into two separate lines (create the file and use "more" with the file) and it worked ok in Win-XP this way.

Code: Select all

@if (@CodeSection == @Batch) @then


@echo off
setlocal

rem Get the number of *displayed* lines in the cmd.exe window
rem Antonio Perez Ayala

for /F "tokens=2 delims=:" %%a in ('mode con') do set /A "min=lastLines=0, max=%%a" & goto nextLine
:nextLine
   set /A "lines=(min+max)/2"
   (for /L %%i in (1,1,%lines%) do @echo/) > testFile.tmp
   cscript //nologo //E:JScript "%~F0" Q
   more /E /C testFile.tmp
   cscript //nologo //E:JScript "%~F0" q
   set /P "test="
   if %test% equ Q (
      set /A "min=lines+1"
      set /P "="
   ) else (
      set /a "max=lines-1"
   )
if %lines% neq %lastLines% set "lastLines=%lines%" & goto nextLine
del testFile.tmp
set /A lines+=1
cls
echo Lines=%lines%
goto :EOF


@end


// JScript section
WScript.CreateObject("WScript.Shell").SendKeys(WScript.Arguments(0)+"{ENTER}");

This last version also works on Win 8.1, so I suppose it is the right version to use in all cases.
Antonio

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

Re: Get the number of lines in cmd.exe window

#6 Post by dbenham » 29 Mar 2016 06:13

I think PowerShell gives a superior result. It is able to return both the window and buffer dimensions without disturbing the window.

Code: Select all

@echo off
setlocal
for /f "tokens=1-4 delims=, " %%A in (
 'powershell -command "&{$H=get-host;$U=$H.ui.rawui;write-host ($U.WindowSize,$U.BufferSize);}"'
) do set /a console.WindowWidth=%%A,^
            console.WindowHeight=%%B,^
            console.BufferrWidth=%%C,^
            console.BufferHeight=%%D
set console


I initially ran across PowerShell's ui.rawui interface at StackOverflow question CMD: Set buffer height independently of window height

There are a number of interesting attributes and methods that could be useful: http://referencesource.microsoft.com/#S ... terface.cs


Dave Benham

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

Re: Get the number of lines in cmd.exe window

#7 Post by npocmaka_ » 29 Mar 2016 10:09

The console class in msdn

Pretty straightforward with jscript.net too (if the compiled file does not bother you):

Code: Select all

@if (@X)==(@Y) @end /* JScript comment
@echo off
setlocal

for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
   set "jsc=%%v"
)

if not exist "%~n0.exe" (
   "%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0"
)

%~n0.exe %*

endlocal & exit /b %errorlevel%


*/
import System;
//import System.IO;

Console.WriteLine( "Console Width " + Console.WindowWidth);
Console.WriteLine( "Console Height " + Console.WindowHeight);
Console.WriteLine( "Console Buffer Width " + Console.BufferWidth);
Console.WriteLine( "Console Buffer Height " + Console.BufferHeight);
Last edited by npocmaka_ on 30 Mar 2016 12:18, edited 1 time in total.

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Get the number of lines in cmd.exe window

#8 Post by aGerman » 29 Mar 2016 14:11

Thanks for the clarification Antonio.

I understand that you can't read anything in the registry that is temporary changed using MODE during runtime.
Although the other difference might be solved (at least I suppose).

Code: Select all

@echo off &setlocal
set "wh="
for /f "tokens=3" %%i in ('2^>nul reg query ^^"HKCU\Console\^%%SystemRoot^%%_system32_cmd.exe^" /v "WindowSize"') do set /a "wh=%%i>>0x10, ww=%%i&0xFFFF"
if not defined wh for /f "tokens=3" %%i in ('reg query "HKCU\Console" /v "WindowSize"') do set /a "wh=%%i>>0x10, ww=%%i&0xFFFF"
echo Window Height %wh%
echo Window Width  %ww%

pause

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Get the number of lines in cmd.exe window

#9 Post by foxidrive » 29 Mar 2016 16:53

Yours works fine in Win 8.1 Antonio, and Dave's Powershell is good.

npocmaka_ wrote:Pretty straightforward with jscript.net too (if the compiled file does not bother you):


Is the Buffer Height correct, npocmaka? I get an odd value.

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Get the number of lines in cmd.exe window

#10 Post by aGerman » 30 Mar 2016 10:02

I get an odd value.

I guess the last 2 lines should read

Code: Select all

Console.WriteLine( "Console Buffer Width " + Console.BufferWidth);
Console.WriteLine( "Console Buffer Height " + Console.BufferHeight);

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

Re: Get the number of lines in cmd.exe window

#11 Post by npocmaka_ » 30 Mar 2016 12:19

aGerman wrote:
I get an odd value.

I guess the last 2 lines should read

Code: Select all

Console.WriteLine( "Console Buffer Width " + Console.BufferWidth);
Console.WriteLine( "Console Buffer Height " + Console.BufferHeight);


Exactly :!: Fixed now. Thanks.

Post Reply