I am trying to write a batch script that is as universal across Windows versions as possible (or at least from XP to 10). Everything is compatible so far (just some echoes and variable setting), except it uses the TIMEOUT.EXE command, which isn't available in XP or below.
I tried copying the exe over to no success. I was wondering if, through some clever coding, if this is possible. I basically need it to wait X amount of seconds before continuing, or allow a keypress to continue.
I tried using sleep.exe from the server 2003 utilities pack while piping it to set /p "=" and vice versa, but that didn't work either.
Any help is appreciated.
There is the choice command command that offers a default option together with a timeout.
For instance:
rem /* Wait for 10 seconds and take the default choice of `0`;
rem you can interrupt waiting with any of the keys `0` to `9` and `A` to `Z`;
rem you cannot use punctuation characters or white-spaces as choices: */
choice /C 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ /D 0 /T 10
rem // The `ErrorLevel` value is going to be set to a non-zero value.
Not the greatest of tools, but using choice with a custom message and a timeout of (5 seconds in this demo), with keystroke interrupt (any key, besides Enter esc etc.)
#echo off
choice /c qwertyuiopasdfghjklzxcvbnm1234567890 /cs /n /M "Timeout is 5 seconds.. press any key to Continue." /D c /T 5
echo 1 > null
there are a lot of ways. PING seems to be the most popular. You can try also
with w32tm
w32tm /stripchart /computer:localhost /period:5 /dataonly /samples:2 1>nul
or wtih typeperf:
typeperf "\System\Processor Queue Length" -si 5 -sc 1 >nul
with mshta:
start "" /w /b /min mshta "javascript:setTimeout(function(){close();},5000);"
I built a batch program that I am currently tweaking to make it more readable/user friendly.
I would like my .bat file to automatically be set to maximize in the .bat file itself.
I read about START /MAX online, but that just opens a new instance of a command prompt window. I don't want to have two .bat files just to maximize one.
I know the windows keys to maximize is ALT+SPACE then X. I got the idea maybe I could use some kind of SendKeys in batch scripting to automate that? I didn't have any luck finding information online.
Is there anyway to program this to maximize within the same .bat instance?
The console window is not measured by w*h in pixels, but in rows and columns. In part, the physical dimensions will be dependent upon the font face and size defined by the user.
The simplest solution is to increase the number of rows and / or columns using the mode command. You can also increase the scroll buffer using a PowerShell helper. As follows is a batch function I've used a few times to manipulate all these values.
:consize <columns> <lines> <scrolllines>
:: change console window dimensions and buffer
mode con: cols=%1 lines=%2
powershell -noprofile "$W=(get-host).ui.rawui; $B=$W.buffersize; $B.height=%3; $W.buffersize=$B"
goto :EOF
The :consize function goes at the bottom of your script, after the final exit /b or goto :EOF at the end of your main script runtime. See this page for more examples of batch functions.
Example usage:
call :consize 80 33 10000
... would expand the window to 80 columns and 33 lines, then expand the vertical scroll buffer to 10,000 lines.
Here's a more complete Batch + PowerShell hybrid script that will move the window to 0,0 then change its width and height to the max columns and rows the screen will accommodate. I had to trial-and-error the $max.Height and $max.Width values a little, so I'm unsure how different display resolutions and different font sizes will affect the script. It ought to be close enough for government work, though.
<# : batch portion
#echo off & setlocal
call :maximize
rem /* ###############################
rem Your main batch code goes here.
rem ############################### */
goto :EOF
:maximize
set "scrollLines=10000"
powershell -noprofile "iex (${%~f0} | out-string)"
goto :EOF
rem // end batch / begin PowerShell hybrid code #>
# Moving the window to coordinates 0,0 requires importing a function from user32.dll.
add-type user32_dll #'
[DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,
int x, int y, int cx, int cy, uint uFlags);
'# -namespace System
# Walk up the process tree until we find a window handle
$id = $PID
do {
$id = (gwmi win32_process -filter "ProcessID='$id'").ParentProcessID
$hwnd = (ps -id $id).MainWindowHandle
} while (-not $hwnd)
# This is where the window moves!
[void][user32_dll]::SetWindowPos($hwnd, [IntPtr]::Zero, 0, 0, 0, 0, 0x41)
# Maximize the window
$console = (get-host).ui.rawui
$max = $console.MaxPhysicalWindowSize
$max.Height -= 1 # account for the titlebar
$max.Width -= 5 # account for the scrollbar
$buffer = $max
$buffer.Height = $env:scrollLines
$console.BufferSize = $buffer
$console.WindowSize = $max
I was thinking about this method:
#echo off
set mytitle=%random%
title %mytitle%
echo WScript.sleep 1000 > %temp%\max-me.vbs
echo WScript.CreateObject("WScript.Shell").AppActivate "%mytitle%" >> %temp%\max-me.vbs
echo WScript.CreateObject("WScript.Shell").SendKeys "%% n" >> %temp%\max-me.vbs
cscript %temp%\max-me.vbs >nul
echo further code goes here...
pause
However, for some reason, sendkeys does not seem to work with cmd windows.
Below mechanism works, but then you lose the existing window & its exit status.
#echo off
if not defined iammaximized (
set iammaximized=1
start /max "" "%0" "%*"
exit
)
echo further code goes here...
pause
There is a little tool called "cmdow.exe" (may be downloaded ad sourceforge.net). But be carefull, this tool allows you to do a lot of things which you might not want to do.
In order to maximize the currend cmd window:
cmdow # /max
In order to restore the current cmd window again:
cmdow # /res
I have an existing MATLAB program which after a keystroke displays an image on the left or right of the screen. The user then indicates via arrow key if the image is on the left or right. The program actually does a lot of other things, but that's the gist. This is for a WinXP computer using MATLAB 2008A.
I would like to do a large number (thousands) of iterations for this program in an attempt to determine why some computers running this program have dying graphics cards. I've already made a number of improvements to simplify existing code and reduce computational time, but I need a to test and show the improvement. GPU-Z records all the hardware variables I'm interested in for now, so I need a keypress script capable of supplying input to the MATLAB program automatically. Ideally, this would be a stand alone macro capable of being run completely independently.
After reading this question, I attempted to modify the batch script as follows:
#if (#CodeSection == #Batch) #then
#echo off
rem Use %SendKeys% to send keys to the keyboard buffer
set SendKeys=CScript //nologo //E:JScript "%~F0"
rem Start the other program in the same Window
start "" /B cmd
%SendKeys% "echo off{ENTER}"
set /P "=Wait and send a command: " < NUL
ping -n 100 -w 1 127.0.0.1 > NUL
%SendKeys% "2"
set /P "=Wait and send a command: " < NUL
%SendKeys% "3"
ping -n 30 -w 1 127.0.0.1 > NUL
%SendKeys% "2"
set /P "=Wait and send a command: " < NUL
%SendKeys% "1"
goto :EOF
#end
// JScript section
var WshShell = WScript.CreateObject("WScript.Shell");
WshShell.SendKeys(WScript.Arguments(0));
In testing, the batch code seems to appropriately enter keystrokes into the active window (cmd, text files, browsers, etc). However, if I attempt to run my MATLAB program simultaneously, the batch execution stalls until the MATLAB program ends. Obviously this is useless to me in the current form.
I'd appreciate any suggestions on where to go from here. Is batch scripting even a viable solution for this kind of automation? If not, any suggestions? I'd prefer to stay away from 3rd party programs as much as possible, but if it's the easiest solution I'll consider it.
I am running a sequence of applications from a batch script and I want to make sure, that the opened program will always be in focus.
We need to ensure this because it's an experimental setup and we want to minimise such hassles as having to change focus to a fullscreen window.
This problem already occurred infrequently when the earlier program exits and for a moment the desktop is visible and the user clicks on some icon on the desktop, and right after that, the next program in the sequence is being processed, the new window is not in focus.
The problem has become much more frequent now that I hid the command window from view.
Any way to force focus for the next program in the sequence, be it a batch command, some settings for the OS (we're on Win XP) or a helper app could be helpful.
If you want to focus another program you can do this.
call focus WindowTitle
exit /b
:focus
setlocal EnableDelayedExpansion
if ["%~1"] equ [""] (
echo Please give the window's title.
exit /b
)
set pr=%~1
set pr=!pr:"=!
echo CreateObject("wscript.shell").appactivate "!pr!" > "%tmp%\focus.vbs"
call "%tmp%\focus.vbs"
del "%tmp%\focus.vbs"
goto :eof
endlocal
I am using vbscript to focus the application.
You need to pass the window's title, not the window's name (whatever.bat).
To make sure you get the right window focused you can set its title.
example:
title WindowTitle
if i got it right, start /f yourapp.exe would start the application in foreground.
Yaron answer will work but would prefer not to create a temp file to execute the script but to embed the code in the batch directly. Or to use jscript which is also part of windows script host and is easier for embedding into batch
Here's a focusOn.batenter link description here that will set the focus on an application based on starting string of the title (will not create temp files which will make it a little bit faster):
#if (#X)==(#Y) #end /* JScript comment
#echo off
cscript //E:JScript //nologo "%~f0" %*
exit /b %errorlevel%
#if (#X)==(#Y) #end JScript comment */
var ARGS=WScript.Arguments;
if (ARGS.Length < 1 ) {
WScript.Echo("No window title passed");
WScript.Quit(1);
}
var sh=new ActiveXObject("WScript.Shell");
if(!sh.AppActivate(ARGS.Item(0))){
WScript.Echo("Cannot find an app with window name starting with: " + ARGS.Item(0));
}
Example usage:
call focusOn.bat Untitled
which should put on focus the notepad (it its title is still "Untitled - Notepad")
I have an application which starts at position 0x0 of my desktop. I want to open it in the center of my desktop. I do not want to open it and use a move command to move it into center, instead my app should start immediately at center position.
Is there any way to do this via command prompt?
You'll need an additional utility such as cmdow.exe to accomplish this. Look specifically at the /mov switch. You can either launch your program from cmdow or run it separately and then invoke cmdow to move/resize it as desired.
Have found that AutoHotKey is very good for window positioning tasks.
Here is an example script. Call it notepad.ahk and then run it from the command line or double click on it.
Run, notepad.exe
WinWait, ahk_class Notepad
WinActivate
WinMove A,, 10, 10, A_ScreenWidth-20, A_ScreenHeight-20
It will start an application (notepad) and then adjust the window size so that it is centered in the window with a 10 pixel border on all sides.
I just found this question while on a quest to do the same thing.
After some experimenting I came across an answer that works the way the OP would want and is simple as heck, but not very general purpose.
Create a shortcut on your desktop or elsewhere (you can use the create-shortcut helper from the right-click menu), set it to run the program "cmd.exe" and run it. When the window opens, position it where you want your window to be. To save that position, bring up the properties menu and hit "Save".
Now if you want you can also set other properties like colors and I highly recommend changing the buffer to be a width of 120-240 and the height to 9999 and enable quick edit mode (why aren't these the defaults!?!)
Now you have a shortcut that will work. Make one of these for each CMD window you want opened at a different location.
Now for the trick, the windows CMD START command can run shortcuts. You can't programmatically reposition the windows before launch, but at least it comes up where you want and you can launch it (and others) from a batch file or another program.
Using a shortcut with cmd /c you can create one shortcut that can launch ALL your links at once by using a command that looks like this:
cmd /c "start cmd_link1 && start cmd_link2 && start cmd_link3"
This will open up all your command windows to your favorite positions and individually set properties like foreground color, background color, font, administrator mode, quick-edit mode, etc... with a single click. Now move that one "link" into your startup folder and you've got an auto-state restore with no external programs at all.
This is a pretty straight-forward solution. It's not general purpose, but I believe it will solve the problem that most people reading this question are trying to solve.
I did this recently so I'll post my cmd file here:
cd /d C:\shortucts
for %%f in (*.lnk *.rdp *.url) do start %%f
exit
Late EDIT: I didn't mention that if the original cmd /c command is run elevated then every one of your windows can (if elevation was selected) start elevated without individually re-prompting you. This has been really handy as I start 3 cmd windows and 3 other apps all elevated every time I start my computer.
This probably should be a comment under the cmdow.exe answer, but here is a simple batch file I wrote to allow for fairly sophisticated and simple control over all windows that you can see in the taskbar.
First step is to run cmdow /t to display a list of those windows. Look at what the image name is in the column Image, then command line:
mycmdowscript.cmd imagename
Here are the contents of the batch file:
:: mycmdowscript.cmd
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
SET IMAGE=%1
SET ACTION=/%2
SET REST=1
SET PARAMS=
:: GET ANY ADDITIONAL PARAMS AND STORE THEM IN A VARIABLE
FOR %%I in (%*) DO (
IF !REST! geq 3 (
SET PARAMS=!PARAMS! %%I
)
SET /A REST+=1
)
FOR /F "USEBACKQ tokens=1,8" %%I IN (`CMDOW /t`) DO (
IF %IMAGE%==%%J (
:: you now have access to the handle in %%I
cmdow %%I %ACTION% !PARAMS!
)
)
ENDLOCAL
#echo on
EXIT /b
example usage
:: will set notepad to 500 500
mycmdowscript.cmd notepad siz 500 500
You could probably rewrite this to allow for multiple actions on a single command, but I haven't tried yet.
For this to work, cmdow.exe must be located in your path. Beware that when you download this, your AV program might yell at you. This tool has (I guess) in the past been used by malware authors to manipulate windows. It is not harmful by itself.
You can use nircmd project here: http://www.nirsoft.net/utils/nircmd.html
Example code:
nircmd win move ititle "cmd.exe" 5 5 10 10
nircmd win setsize ititle "cmd.exe" 30 30 100 200
nircmd cmdwait 1000 win setsize ititle "cmd.exe" 30 30 1000 600
If you are happy to run a batch file along with a couple of tiny helper programs, a complete solution is posted here:
How can a batch file run a program and set the position and size of the window? - Stack Overflow (asked: May 1, 2012)
Bill K.'s answer was the most elegant if you just want to start a window at startup or start from a shortcut on the desktop.
Just open the window where you want it,
right click and choose properties.
select Layout
uncheck "let system position window"
and click OK.
Window will now open just where you want it.
You can set font and window colors at the same time on other tabs.
sweet.
Thanks To FuzzyWuzzy , set the following code ( Quick & Dirty Example for 1920x1080 screen resolution - without automatic width and height calculation or function use etc ) in AutoHotKey
to achive the following :
v_cmd = c:\temp\1st_Monitor.ps1
Run, Powershell.exe -executionpolicy remotesigned -File %v_cmd%
SetTitleMatchMode 2
SetTitleMatchMode Fast
WinWait, PowerShell
Sleep, 1000
;A = Active window - [x,y,width,height]
WinMove A,, 0, 0,1920,500
v_cmd = c:\temp\2nd_Monitor.ps1
Run, Powershell.exe -executionpolicy remotesigned -File %v_cmd%
WinWait, PowerShell
Sleep, 1000
;A = Active window - [x,y,width,height]
WinMove A,, 0, 500,960,400
v_cmd = c:\temp\3rd_Monitor.ps1
Run, Powershell.exe -executionpolicy remotesigned -File %v_cmd%
WinWait, PowerShell
Sleep, 1000
;A = Active window - [x,y,width,height]
WinMove A,, 960, 500,960,400
SMALL EDIT
same code with Auto X / Y screen size calculation [ 4 monitors ], yet, can be used for 3 / 2 monitors as well.
Screen_X = %A_ScreenWidth%
Screen_Y = %A_ScreenHeight%
v_cmd = c:\temp\1st_Monitor.ps1
Run, Powershell.exe -executionpolicy remotesigned -File %v_cmd%
SetTitleMatchMode 2
SetTitleMatchMode Fast
WinWait, PowerShell
Sleep, 1000
;A = Active window - [x,y,width,height]
WinMove A,, 0, 0,Screen_X/2,Screen_Y/2
v_cmd = c:\temp\2nd_Monitor.ps1
Run, Powershell.exe -executionpolicy remotesigned -File %v_cmd%
WinWait, PowerShell
Sleep, 1000
;A = Active window - [x,y,width,height]
WinMove A,, Screen_X/2, 0,Screen_X/2,Screen_Y/2
v_cmd = c:\temp\3rd_Monitor.ps1
Run, Powershell.exe -executionpolicy remotesigned -File %v_cmd%
WinWait, PowerShell
Sleep, 1000
;A = Active window - [x,y,width,height]
WinMove A,, 0, Screen_Y/2,Screen_X/2,Screen_Y/2
v_cmd = c:\temp\4th_Monitor.ps1
Run, Powershell.exe -executionpolicy remotesigned -File %v_cmd%
WinWait, PowerShell
Sleep, 1000
;A = Active window - [x,y,width,height]
WinMove A,, Screen_X/2, Screen_Y/2,Screen_X/2,Screen_Y/2
I too wanted to do this and came across this thread: Positioning CMD Window. No external files to download as it creates a small bit of VBScript on the fly to do all the lifting. All you need to do is specify your X & Y coordinates in the following section: Cscript //nologo "%~DP0pos.vbs" "%~F0" 100 50. The .vbs script is also removed after it has been executed too so there is no need to tidy anything up.
Place this at the top of your batch file:
REM - Position the CMD Window Using .VBS -----------------------------------------
REM == MUST BE AT The Begining of The Batch =========
IF "%~1" == "RestartedByVBS" Goto :Code
REM Create the VBScript, if not exist
IF NOT EXIST "%~DP0pos.vbs" (
(FOR /F "tokens=1*" %%a in ('findstr "^VBS:" ^< "%~F0"') do (
echo(%%b
)) > "%~DP0pos.vbs"
)
REM Start "" "%~DP0pos.vbs" "%~F0" 100 50
Cscript //nologo "%~DP0pos.vbs" "%~F0" 100 50
EXIT /B
:code
DEL /Q "%~DP0pos.vbs"
REM ------------------------------------------------------------------------------
PLACE THE CONTENTS OF YOUR OWN BATCH FILE HERE
And this at the bottom:
REM - Position the CMD Window Using .VBS -----------------------------------------
:Pos <BatchFileName> <X_Coordinate> <Y_Coordinate>
REM This Function will take three inputs: the name of the Batch file to execute
REM and the X and Y Coordinates to Position its CMD window
VBS: Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
VBS: Set objConfig = objWMIService.Get("Win32_ProcessStartup")
VBS: objConfig.SpawnInstance_
VBS: objConfig.X = WScript.Arguments(1)
VBS: objConfig.Y = WScript.Arguments(2)
VBS: Set objNewProcess = objWMIService.Get("Win32_Process")
VBS: intReturn = objNewProcess.Create( chr(34) & WScript.Arguments(0) &chr(34)& " RestartedByVBS", Null, objConfig, intProcessID)
REM ------------------------------------------------------------------------------
Enjoy :)