Complete control of cmd windows

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

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

Re: Complete control of cmd windows

#16 Post by Aacini » 05 Oct 2022 07:53

aGerman wrote:
05 Oct 2022 03:41
Since loading a PowerShell process is comparatively slow it might be worth to gather all information with only one call.
It took me some minutes to figure out how the macro has to look like for processing in a FOR /F loop. However, finally I succeeded :)

Code: Select all

@echo off &setlocal

set ConsoleInfo=powershell -nop -ep Bypass -c ^"$w=Add-Type -Name WAPI -PassThru -MemberDefinition '^
%===% [DllImport(\"kernel32.dll\"^)] public static extern void GetCurrentConsoleFont(IntPtr hOut,int isMax,int[] info^);^
%===% [DllImport(\"kernel32.dll\"^)] public static extern IntPtr CreateFile(string name,int acc,int share,IntPtr sec,int how,int flags,IntPtr tmplt^);^
%===% [DllImport(\"kernel32.dll\"^)] public static extern void CloseHandle(IntPtr h^);';^
%=% [int[]]$info=0,0;$h=$w::CreateFile('CONOUT$',0xC0000000,2,[IntPtr]::Zero,3,0,[IntPtr]::Zero^);$w::GetCurrentConsoleFont($h,0,$info^);$w::CloseHandle($h^);^
%=% $r=$host.UI.RawUI;$c=$r.WindowSize;$l=$r.MaxPhysicalWindowSize;^
%=% \"cfx^=$($info[1] -band 0xFFFF^)^,cfy^=$(($info[1] -shr 16^) -band 0xFFFF^)^,ccx^=$($c.Width^)^,ccy^=$($c.Height^)^,clx^=$($l.Width^)^,cly^=$($l.Height^)\";^"

for /f %%i in ('%ConsoleInfo%') do set /a "%%i"
echo console font size: %cfx%, %cfy%
echo console current size: %ccx%, %ccy%
echo console largest size: %clx%, %cly%

pause
Steffen

I like this very much! :D

I modified the code in order to make it clearer, trying to understand it. This is my final version:

Code: Select all

@echo off &setlocal

set ConsoleInfo=^
powershell ^
 ^"$w=Add-Type -Name WAPI -PassThru -MemberDefinition ' ^
      [DllImport(\"kernel32.dll\"^)] public static extern ^
         IntPtr CreateFile(string name,int acc,int share,IntPtr sec,int how,int flags,IntPtr tmplt^); ^
      [DllImport(\"kernel32.dll\"^)] public static extern void GetCurrentConsoleFont(IntPtr hOut,int isMax,int[] info^); ^
      [DllImport(\"kernel32.dll\"^)] public static extern void CloseHandle(IntPtr h^); ^
   '; ^
   [int[]]$info=0,0; ^
   $h=$w::CreateFile('CONOUT$',0xC0000000,2,[IntPtr]::Zero,3,0,[IntPtr]::Zero^); ^
   $w::GetCurrentConsoleFont($h,0,$info^); ^
   $w::CloseHandle($h^); ^
   \"cfx^=$($info[1] -band 0xFFFF^)^,cfy^=$($info[1] -shr 16^)\"; ^
   $r=$host.UI.RawUI; ^
   $c=$r.WindowSize; ^
   \"ccx^=$($c.Width^)^,ccy^=$($c.Height^)\"; ^
   $l=$r.MaxPhysicalWindowSize; ^
   \",clx^=$($l.Width^)^,cly^=$($l.Height^)\"; ^
 ^"

for /f %%i in ('%ConsoleInfo%') do set /a "%%i"
echo console font size: %cfx%, %cfy%
echo console current size: %ccx%, %ccy%
echo console largest size: %clx%, %cly%

pause
You don't need the PS switches to execute plain PS code. It is not necessary to AND with 0xFFFF after SHR 16 the value.

Antonio

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

Re: Complete control of cmd windows

#17 Post by aGerman » 05 Oct 2022 08:35

I'm good with your version Antonio :)
Only some words to explain why I did things like I did.
- The funny %=% variables are a workaround to shorten the content of the macro, and still having some kind of indentation in the code at the same time. They expand to "nothing" instead of having a high number of spaces in the variable content.
- I agree with you that the -band 0xFFFF is not necessary in this case because the height of the font will never be a negative value. In other cases, however, it might be necessary because as soon as the Most Significant Bit is 1, right-shifting leads to ones getting shifted in.

Steffen

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Complete control of cmd windows

#18 Post by einstein1969 » 06 Oct 2022 04:10

@aGerman
I like one call for all the work! :)

@Antonio
I prefer your version with more readability! :)

thanks to both of you, I am testing for any bugs and to move on to the next step.

At this point, one important thing is missing that relates to both the screen resolution and the font size. That is, the centering of the console on the screen or, more generally, the positioning.

Do you know if it is possible to do this?

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

Re: Complete control of cmd windows

#19 Post by aGerman » 06 Oct 2022 07:29

Possible, yes, of course.
viewtopic.php?t=8822
I'm afraid at some point it could have been easier to just do the whole stuff in PowerShell :lol:

FWIW: I don't want to discourage you because things like that are nice exercises. However, recently I had a look into my crystal ball and it's been showing me that the Windows Terminal superceded the good ol' console host. (It already ships with Win 11 and can be set as default rather than conhost.)

Steffen

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Complete control of cmd windows

#20 Post by einstein1969 » 07 Oct 2022 05:38

aGerman wrote:
06 Oct 2022 07:29
Possible, yes, of course.
viewtopic.php?t=8822
I'm afraid at some point it could have been easier to just do the whole stuff in PowerShell :lol:

FWIW: I don't want to discourage you because things like that are nice exercises. However, recently I had a look into my crystal ball and it's been showing me that the Windows Terminal superceded the good ol' console host. (It already ships with Win 11 and can be set as default rather than conhost.)

Steffen
They are exercises. I tested multithreading on the same console. It behaves well with a few artifacts I think solvable with mutexes, semaphore, lock or other such mechanisms. Antonio is good at this.

I had to lower the set /p buffer a bit to improve process concurrency.

I have not yet tested the positioning of the window well, as the macro creates problems for me if I call it inside a procedure and then the centering formula is really difficult to find.

This is the new script that uses /MAX of the "start" command and /B. It creates me, only a few times and with certain fonts, a scroll bar at the bottom.

Code: Select all

@echo off & setlocal enableDelayedExpansion & if NOT "%1"=="" goto :dispatch

rem save this script in UTF-8

rem restart maximized

Start "Sphere" /MAX "%~f0" max

goto :eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:dispatch

if "%1"=="max" (

	call :GetInfo

	rem setting request console size and remove buffers size on max
	mode CON: COLS=!MaxConsoleSize.X! LINES=!MaxConsoleSize.Y!

	rem multithread 9 thread

	set /A deltaX=MaxConsoleSize.X/3, deltaY=MaxConsoleSize.Y/3, Radius=DeltaY/2

	start "" /B "%~f0" sphere Red     1 1 !deltaX! !deltaY! !Radius!
	start "" /B "%~f0" sphere Green   !deltaX! 1 !deltaX!*2 !deltaY! !Radius!
	start "" /B "%~f0" sphere Blue    !deltaX!*2 1 !deltaX!*3 !deltaY! !Radius!

	start "" /B "%~f0" sphere Yellow  1 !deltaY!+1 !deltaX! !deltaY!*2 !Radius!
	start "" /B "%~f0" sphere Cyan    !deltaX! !deltaY!+1 !deltaX!*2 !deltaY!*2 !Radius!
	start "" /B "%~f0" sphere Magenta !deltaX!*2 !deltaY!+1 !deltaX!*3 !deltaY!*2 !Radius!

	start "" /B "%~f0" sphere White   1 !deltaY!*2+1 !deltaX! !deltaY!*3 !Radius!
	start "" /B "%~f0" sphere Orange  !deltaX! !deltaY!*2+1 !deltaX!*2 !deltaY!*3 !Radius!
	start "" /B "%~f0" sphere Pink    !deltaX!*2 !deltaY!*2+1 !deltaX!*3 !deltaY!*3 !Radius!

	pause>nul
)

if "%1"=="sphere" call :sphere %2 %3 %4 %5 %6 %7

goto :eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:sphere color Begin.X Begin.Y End.X End.Y Radius

rem title %1 %2 %3 %4 %5 %6
rem pause 

call :init

set /A Bimg.x=%2, Bimg.y=%3
set /A Eimg.x=%4, Eimg.y=%5
set /A Radius=%6

rem font size in pixels
set /A xc=FontSize.X, yc=FontSize.Y

rem draw a circle (x-x0)^2+(y-y0)^2=r^2 . Implicit equation for simpler math.

rem set radius and center in cmd windows, assume screen ratio greater than one ie 1280/720=1.777

set /A "R=Radius*yc, X0=((Eimg.x-Bimg.x)/2+Bimg.x)*xc, Y0=Bimg.y*yc+R"

rem setting step for better smoothing colors
set /A "mS=-(R*R), step=255*100000/-mS, stepL=128*100000/-mS"

For /L %%y in (!Bimg.y!,1,!Eimg.y!) do (

  For /L %%x in (!Bimg.x!,1,!Eimg.x!) do (

	rem calculate circle equation and color for smooting.
	rem This code generate multiple circlesof different color and simulate a 3D sphere.
        set /A px=%%x*xc, py=%%y*yc, x=px-x0, y=py-y0, S=y*y+x*x-R*R, C=-S*step/100000, CL=-S*stepL/100000"

	if !S! leq 0 (
		if "%1"=="Red" %plot% %%x %%y !C! 0 0
		if "%1"=="Green" %plot% %%x %%y 0 !C! 0
		if "%1"=="Blue" %plot% %%x %%y 0 0 !C!
		if "%1"=="Yellow" %plot% %%x %%y !C! !C! 0
		if "%1"=="Cyan" %plot% %%x %%y 0 !C! !C!
		if "%1"=="Magenta" %plot% %%x %%y !C! 0 !C!
		if "%1"=="White" %plot% %%x %%y !C! !C! !C!
		if "%1"=="Orange" %plot% %%x %%y !C! !CL! 0
		if "%1"=="Pink" %plot% %%x %%y !C! 0 !CL!
		if "%1"=="Salmon" %plot% %%x %%y !C! !CL! !CL!
		if "%1"=="Navy" %plot% %%x %%y 0 0 !CL!
		if "%1"=="Gray" %plot% %%x %%y !CL! !CL! !CL!
	)
  )
) 
%flush%

pause>nul
goto :eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:GetInfo

rem many thanks aGerman and Aacini
set ConsoleInfo=^
powershell ^
 ^"$w=Add-Type -Name WAPI -PassThru -MemberDefinition ' ^
      [DllImport(\"kernel32.dll\"^)] public static extern ^
         IntPtr CreateFile(string name,int acc,int share,IntPtr sec,int how,int flags,IntPtr tmplt^); ^
      [DllImport(\"kernel32.dll\"^)] public static extern void GetCurrentConsoleFont(IntPtr hOut,int isMax,int[] info^); ^
      [DllImport(\"kernel32.dll\"^)] public static extern void CloseHandle(IntPtr h^); ^
   '; ^
   [int[]]$info=0,0; ^
   $h=$w::CreateFile('CONOUT$',0xC0000000,2,[IntPtr]::Zero,3,0,[IntPtr]::Zero^); ^
   $w::GetCurrentConsoleFont($h,0,$info^); ^
   $w::CloseHandle($h^); ^
   \"cfx^=$($info[1] -band 0xFFFF^)^,cfy^=$($info[1] -shr 16^)\"; ^
   $r=$host.UI.RawUI; ^
   $c=$r.WindowSize; ^
   \"ccx^=$($c.Width^)^,ccy^=$($c.Height^)\"; ^
   $l=$r.MaxPhysicalWindowSize; ^
   \",clx^=$($l.Width^)^,cly^=$($l.Height^)\"; ^
 ^"

for /f %%i in ('%ConsoleInfo%') do set /a "%%i"

rem font size in pixels
set /a "FontSize.X=%cfx%, FontSize.Y=%cfy%"

rem max/largest Size of cmd window/console window
set /a "MaxConsoleSize.X=%clx%, MaxConsoleSize.Y=%cly%"

rem Current Size of cmd window/console window
set /a "ConsoleSize.X=%ccx%, ConsoleSize.Y=%ccy%"

rem get resolution of screen
for /f "usebackq tokens=1,2 delims= " %%x in (
`mshta "javascript:new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write(screen.width+' '+screen.height);close();noflash"`
) do set /A Screen.Width=%%x, Screen.Height=%%y

goto :eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:init

rem for ansi sequence
for /F %%a in ('echo prompt $E^| %ComSpec%') do set "ESC=%%a"

:: Hide the cursor
<nul set /p "=!ESC![?25l"

rem this code must execute after GetConsoleFontSize macro, if not this change font family to TERMINAL/RASTER, in window 10
chcp 65001 >nul

rem clear environment for faster execution of SET command
(
set "Path=%SystemRoot%\system32"
for /F "Tokens=1 delims==" %%v in ('set') do if not %%v==ESC if not %%v==TMP if not %%v==Path set "%%v="
set /a "FontSize.X=%FontSize.X%, FontSize.Y=%FontSize.Y%"
set /a "ConsoleSize.X=%ConsoleSize.X%, ConsoleSize.Y=%ConsoleSize.Y%"
set /a "MaxConsoleSize.X=%MaxConsoleSize.X%, MaxConsoleSize.Y=%MaxConsoleSize.Y%"
set /A Screen.Width=%Screen.Width%, Screen.Height=%Screen.Height%
)

rem ALT+219
set "Char=█"
rem set "Char=*"

rem for macro definition/readability
(set \n=^^^
%= This creates an escaped Line Feed - DO NOT ALTER =%
)

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: macro Plot=Screen.Setpixel X Y R G B

set "Buffer="

set Plot=for %%# in (1 2) do if %%#==2 (%\n%
	for /f "tokens=1-5 delims=, " %%1 in ("^!args^!") do ( %\n%
		if not defined Buffer (%\n%
			set "Buffer=^!ESC^![%%2;%%1H^!ESC^![38;2;%%3;%%4;%%5m^!Char^!" %\n%
		) else ( %\n%
			if "^!Buffer:~100,1^!"=="" ( %\n%
				set "Buffer=^!Buffer^!^!ESC^![%%2;%%1H^!ESC^![38;2;%%3;%%4;%%5m^!Char^!" %\n%
			) else ( %\n%
				^<nul set /p "=^!Buffer^!^!ESC^![%%2;%%1H^!ESC^![38;2;%%3;%%4;%%5m^!Char^!^!ESC^![0m" %\n%
				set "Buffer=" %\n%
			) %\n%
		) %\n%
)) else set args=

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Flush flush the variable buffer.

set Flush=^<nul set /p "=^!Buffer^!^!ESC^![0m" ^& set "Buffer="

goto :eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Image

execute this and change font family/size and zoom from 100% to 125% for testing under diffent conditions

:) :) :)

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

Re: Complete control of cmd windows

#21 Post by aGerman » 07 Oct 2022 10:38

... and with certain fonts, a scroll bar at the bottom
I guess that can be avoided. You execute the ConsoleInfo macro in the already maximized window. So, use ConsoleSize rather than MaxConsoleSize for both the MODE command and your delta calculations.

Steffen

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Complete control of cmd windows

#22 Post by einstein1969 » 07 Oct 2022 15:11

aGerman wrote:
07 Oct 2022 10:38
... and with certain fonts, a scroll bar at the bottom
I guess that can be avoided. You execute the ConsoleInfo macro in the already maximized window. So, use ConsoleSize rather than MaxConsoleSize for both the MODE command and your delta calculations.

Steffen
Thanks, it works.

I'm having trouble with the "move" I think it's the various setlocal. I tried to modify the procedure with EnableDelayedExpansion but I couldn't :(.

This is the code.

Code: Select all

@echo off & setlocal enableDelayedExpansion & if NOT "%1"=="" goto :subs

rem save this script in UTF-8

rem multithread

rem test other mode (aspect ratio /font size)
Start "Sphere" "%0" Red

::Start "Sphere" "%0" Green
::Start "Sphere" "%0" Blue
::Start "Sphere" "%0" Yellow
::Start "Sphere" "%0" Cyan
::Start "Sphere" "%0" Magenta
::Start "Sphere" "%0" White
::Start "Sphere" "%0" Orange
::Start "Sphere" "%0" Pink
::Start "Sphere" "%0" Salmon
::Start "Sphere" "%0" Navy
::Start "Sphere" "%0" Gray

:: TODO concurrent access of console with ansi escape sequences

goto :eof

:subs

title %1

call :init

rem setting console size in char 50x50 or max
if NOT "%2"=="max" (
	set /A img.x=50, img.y=50
) else (
	set /A img.x=ConsoleSize.X-2, img.y=ConsoleSize.Y
)

rem setting request console size and remove buffers size on max
mode CON: COLS=!img.x! LINES=!img.y!

rem is strange formula but work well
set /A "center.x=(Screen.Width-img.x*FontSize.X)/2-8"
set /A "center.y=(Screen.height-img.y*FontSize.Y)/2-8-35"

rem echo %Screen.Width% %img.x% %FontSize.X% %center.x% %center.y%
rem pause

%move_window% %center.x% %center.y%

rem font size in pixels
set /A xc=FontSize.X, yc=FontSize.Y

set /A width=img.x*xc, height=img.y*yc

rem calculate bigger from width and height, use for radius
if !width! leq !height! ( set /a res=width ) else ( set /a res=height )

rem draw a circle (x-x0)^2+(y-y0)^2=r^2 . Implicit equation for simpler math.

rem set radius and center in cmd windows

set /A "R=res/2, X0=width/2, Y0=height/2"

rem setting step for better smoothing colors
set /A "mS=-(R*R), step=255*100000/-mS, stepL=128*100000/-mS"

For /L %%y in (1,1,!img.y!) do (

  For /L %%x in (1,1,!img.x!) do (

	rem calculate circle equation and color for smooting.
	rem This code generate multiple circlesof different color and simulate a 3D sphere.
        set /A px=%%x*xc, py=%%y*yc, x=px-x0, y=py-y0, S=y*y+x*x-R*R, C=-S*step/100000, CL=-S*stepL/100000"

	if !S! leq 0 (
		if "%1"=="Red" %plot% %%x %%y !C! 0 0
		if "%1"=="Green" %plot% %%x %%y 0 !C! 0
		if "%1"=="Blue" %plot% %%x %%y 0 0 !C!
		if "%1"=="Yellow" %plot% %%x %%y !C! !C! 0
		if "%1"=="Cyan" %plot% %%x %%y 0 !C! !C!
		if "%1"=="Magenta" %plot% %%x %%y !C! 0 !C!
		if "%1"=="White" %plot% %%x %%y !C! !C! !C!
		if "%1"=="Orange" %plot% %%x %%y !C! !CL! 0
		if "%1"=="Pink" %plot% %%x %%y !C! 0 !CL!
		if "%1"=="Salmon" %plot% %%x %%y !C! !CL! !CL!
		if "%1"=="Navy" %plot% %%x %%y 0 0 !CL!
		if "%1"=="Gray" %plot% %%x %%y !CL! !CL! !CL!
	)
  )
) 
%flush%

pause>nul
goto :eof

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:init

rem for ansi sequence
for /F %%a in ('echo prompt $E^| %ComSpec%') do set "ESC=%%a"

:: Hide the cursor
<nul set /p "=!ESC![?25l"

rem many thanks aGerman and Aacini
set ConsoleInfo=^
powershell ^
 ^"$w=Add-Type -Name WAPI -PassThru -MemberDefinition ' ^
      [DllImport(\"kernel32.dll\"^)] public static extern ^
         IntPtr CreateFile(string name,int acc,int share,IntPtr sec,int how,int flags,IntPtr tmplt^); ^
      [DllImport(\"kernel32.dll\"^)] public static extern void GetCurrentConsoleFont(IntPtr hOut,int isMax,int[] info^); ^
      [DllImport(\"kernel32.dll\"^)] public static extern void CloseHandle(IntPtr h^); ^
   '; ^
   [int[]]$info=0,0; ^
   $h=$w::CreateFile('CONOUT$',0xC0000000,2,[IntPtr]::Zero,3,0,[IntPtr]::Zero^); ^
   $w::GetCurrentConsoleFont($h,0,$info^); ^
   $w::CloseHandle($h^); ^
   \"cfx^=$($info[1] -band 0xFFFF^)^,cfy^=$($info[1] -shr 16^)\"; ^
   $r=$host.UI.RawUI; ^
   $c=$r.WindowSize; ^
   \"ccx^=$($c.Width^)^,ccy^=$($c.Height^)\"; ^
   $l=$r.MaxPhysicalWindowSize; ^
   \",clx^=$($l.Width^)^,cly^=$($l.Height^)\"; ^
 ^"

for /f %%i in ('%ConsoleInfo%') do set /a "%%i"

rem font size in pixels
set /a "FontSize.X=%cfx%, FontSize.Y=%cfy%"

rem max/largest Size of cmd window/console window
set /a "MaxConsoleSize.X=%clx%, MaxConsoleSize.Y=%cly%"

rem Current Size of cmd window/console window
set /a "ConsoleSize.X=%ccx%, ConsoleSize.Y=%ccy%"

rem get resolution of screen
for /f "usebackq tokens=1,2 delims= " %%x in (`mshta "javascript:new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write(screen.width+' '+screen.height);close();noflash"`) do set /A Screen.Width=%%x, Screen.Height=%%y

rem clear environment for faster execution of SET command
(
rem set "Path=%SystemRoot%\system32"
for /F "Tokens=1 delims==" %%v in ('set') do if not %%v==ESC if not %%v==TMP if not %%v==Path if not %%v==SystemRoot set "%%v="
set /a "FontSize.X=%FontSize.X% , FontSize.Y=%FontSize.Y%"
set /a "ConsoleSize.X=%ConsoleSize.X% , ConsoleSize.Y=%ConsoleSize.Y%"
set /a "MaxConsoleSize.X=%MaxConsoleSize.X% , MaxConsoleSize.Y=%MaxConsoleSize.Y%"
set /A Screen.Width=%Screen.Width%, Screen.Height=%Screen.Height%
)

rem this code must execute after GetConsoleFontSize macro, if not this change font family to TERMINAL/RASTER, in window 10
chcp 65001 >nul

rem ALT+219
set "Char=█"
rem set "Char=*"

rem for macro definition/readability
(set \n=^^^
%= This creates an escaped Line Feed - DO NOT ALTER =%
)

setlocal DisableDelayedExpansion

set move_window=for %%i in (1 2) do if %%i==2 (%\n%
%=% for /f "tokens=1*" %%j in ("!arg!") do (%\n%
%=====% powershell.exe -NoProfile -ExecutionPolicy Bypass -Command ^"try{$c=Add-Type -Name WinAPI -PassThru -MemberDefinition '^
%=====% [DllImport(\"user32.dll\")] public static extern int SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);^
%=====% [DllImport(\"kernel32.dll\")] public static extern IntPtr GetConsoleWindow();';^
%=====% $x=0; $y=0;^
%=====% if (([Int32]::TryParse(\"%%~j\", [ref]$x) -eq $false) -or ([Int32]::TryParse(\"%%~k\", [ref]$y) -eq $false)){^
%=========% [Console]::Error.WriteLine(\"Syntax Error`r`n Usage:`r`n%%move_window%% X Y`r`n   X  left side of the window`r`n   Y  top of the window\");^
%=========% exit 1;^
%=====% }^
%=====% exit [int]($c::SetWindowPos($c::GetConsoleWindow(), [IntPtr]::Zero, $x, $y, 0, 0, 5) -eq 0);}catch{exit 1;}^"%\n%
%=% )%\n%
%=% endlocal%\n%
) else setlocal EnableDelayedExpansion ^&set arg=

rem %move_window% 100 50
rem echo %errorlevel%
rem pause

setlocal EnableDelayedExpansion

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: macro Plot=Screen.Setpixel X Y R G B

set "Buffer="

set Plot=for %%# in (1 2) do if %%#==2 (%\n%
	for /f "tokens=1-5 delims=, " %%1 in ("^!args^!") do ( %\n%
		if not defined Buffer (%\n%
			set "Buffer=^!ESC^![%%2;%%1H^!ESC^![38;2;%%3;%%4;%%5m^!Char^!" %\n%
		) else ( %\n%
			if "^!Buffer:~1500,1^!"=="" ( %\n%
				set "Buffer=^!Buffer^!^!ESC^![%%2;%%1H^!ESC^![38;2;%%3;%%4;%%5m^!Char^!" %\n%
			) else ( %\n%
				^<nul set /p "=^!Buffer^!^!ESC^![%%2;%%1H^!ESC^![38;2;%%3;%%4;%%5m^!Char^!^!ESC^![0m" %\n%
				set "Buffer=" %\n%
			) %\n%
		) %\n%
)) else set args=

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Flush flush the variable buffer.

set Flush=^<nul set /p "=^!Buffer^!^!ESC^![0m" ^& set "Buffer="

goto :eof

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

Re: Complete control of cmd windows

#23 Post by aGerman » 07 Oct 2022 15:32

It's not necessary to disable the delayed expansion. Just escape the exclamation points like you did in the Plot macro.

Code: Select all

set move_window=for %%i in (1 2) do if %%i==2 (%\n%
%=% for /f "tokens=1*" %%j in ("^!arg^!") do (%\n%
... etc.

Steffen

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Complete control of cmd windows

#24 Post by einstein1969 » 08 Oct 2022 04:18

not work :evil:

this is an extract of previus script

Code: Select all

...
rem for macro definition/readability
(set \n=^^^
%= This creates an escaped Line Feed - DO NOT ALTER =%
)

rem setlocal DisableDelayedExpansion

set move_window=for %%i in (1 2) do if %%i==2 (%\n%
%=% for /f "tokens=1*" %%j in ("^!arg^!") do (%\n%
%=====% powershell.exe -NoProfile -ExecutionPolicy Bypass -Command ^"try{$c=Add-Type -Name WinAPI -PassThru -MemberDefinition '^
%=====% [DllImport(\"user32.dll\")] public static extern int SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);^
%=====% [DllImport(\"kernel32.dll\")] public static extern IntPtr GetConsoleWindow();';^
%=====% $x=0; $y=0;^
%=====% if (([Int32]::TryParse(\"%%~j\", [ref]$x) -eq $false) -or ([Int32]::TryParse(\"%%~k\", [ref]$y) -eq $false)){^
%=========% [Console]::Error.WriteLine(\"Syntax Error`r`n Usage:`r`n%%move_window%% X Y`r`n   X  left side of the window`r`n   Y  top of the window\");^
%=========% exit 1;^
%=====% }^
%=====% exit [int]($c::SetWindowPos($c::GetConsoleWindow(), [IntPtr]::Zero, $x, $y, 0, 0, 5) -eq 0);}catch{exit 1;}^"%\n%
%=% )%\n%
%=% endlocal%\n%
) else setlocal EnableDelayedExpansion ^&set arg=

%move_window% 100 50
echo %errorlevel%
pause

rem setlocal EnableDelayedExpansion
...

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Complete control of cmd windows

#25 Post by einstein1969 » 08 Oct 2022 04:24

i have escaped also ")" and "," but nothing...

Code: Select all

rem for macro definition/readability
(set \n=^^^
%= This creates an escaped Line Feed - DO NOT ALTER =%
)

rem setlocal DisableDelayedExpansion

set move_window=for %%i in (1 2) do if %%i==2 (%\n%
%=% for /f "tokens=1*" %%j in ("^!arg^!") do (%\n%
%=====% powershell.exe -NoProfile -ExecutionPolicy Bypass -Command ^"try{$c=Add-Type -Name WinAPI -PassThru -MemberDefinition '^
%=====% [DllImport(\"user32.dll\"^)] public static extern int SetWindowPos(IntPtr hWnd^, IntPtr hWndInsertAfter^, int X^, int Y^, int cx^, int cy^, uint uFlags^);^
%=====% [DllImport(\"kernel32.dll\"^)] public static extern IntPtr GetConsoleWindow(^);';^
%=====% $x=0; $y=0;^
%=====% if (([Int32]::TryParse(\"%%~j\"^, [ref]$x^) -eq $false^) -or ([Int32]::TryParse(\"%%~k\"^, [ref]$y^) -eq $false^)^){^
%=========% [Console]::Error.WriteLine(\"Syntax Error`r`n Usage:`r`n%%move_window%% X Y`r`n   X  left side of the window`r`n   Y  top of the window\"^);^
%=========% exit 1;^
%=====% }^
%=====% exit [int]($c::SetWindowPos($c::GetConsoleWindow(^)^, [IntPtr]::Zero^, $x^, $y^, 0^, 0^, 5^) -eq 0^);}catch{exit 1;}^"%\n%
%=% )%\n%
%=% endlocal%\n%
) else setlocal EnableDelayedExpansion ^&set arg=

%move_window% 100 50
echo %errorlevel%
pause

rem setlocal EnableDelayedExpansion
EDIT: now works , I missed a ","
Last edited by einstein1969 on 08 Oct 2022 04:32, edited 1 time in total.

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

Re: Complete control of cmd windows

#26 Post by aGerman » 08 Oct 2022 04:29

The first attempt works for me.

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Complete control of cmd windows

#27 Post by einstein1969 » 08 Oct 2022 04:33

Work, Work, I have edit previus post! :oops:

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Complete control of cmd windows

#28 Post by einstein1969 » 08 Oct 2022 04:36

Can I remove the setlocal and the endlocal?

Why this?

Code: Select all

%=% endlocal%\n%
) else setlocal EnableDelayedExpansion ^&set arg=

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

Re: Complete control of cmd windows

#29 Post by aGerman » 08 Oct 2022 04:40

I guess you could since you already call it in an environment where delayed expansion is turned on.
It's there to expand !arg! if delayed expansion was turned off.

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Complete control of cmd windows

#30 Post by einstein1969 » 08 Oct 2022 04:45

in the macro you need the delayed expansion only for the part " !Args! " , right?

Post Reply