Focus a batch-started application - windows

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")

Related

Windows Batch, how to pause then close window?

Windows batch file, I want the window close itself after user hit a key.
For example
#echo off
echo ---------------------
echo hit a key will close
echo ---------------------
pause
exit /b
but it won't close
You dont need to add echo hit a key will close; basically the pause
command already says that for you.
But if you want to add your own custom message you can add
pause>nul
and add an echo above that for a custom exit message,
then type
exit
after the pause >nul.
In the RPG I'm working on, I use a quitgame.bat as I also need to close other processes when the batch exits.
CHOICE is the command I use for most input, and I present the option to 'Q'uit at all times (single keypress to exit the game). when the user selects this Choice, the errorlevel check has the Batch go to a label to Call my quitgame.bat
Set ask=CHOICE /N /C:
Set then= /M ""
Set do=IF ERRORLEVEL ==
%ask%nqfmie%then%
%do%6 GOTO enterSL
%do%5 GOTO viewinv
%do%4 GOTO market
%do%3 GOTO forcereset
%do%2 GOTO quit
%do%1 GOTO nextpage
:quit
CALL "%Quitgame%"
In my quitprogram:
#ECHO OFF
REM program to taskkill vbs scripts and child processes
CALL "%killmusic%"
REM deletes all vbs scripts created during programs execution
DEL /Q %sounds%\*.vbs
REM closes the command console
EXIT
If you dont have other processes or multiple bat files to warrant calling another program, just use a label you can goto using choice.
:quit
Exit

how do i kill an entire process after its finished from a batch file

I'm looking to kill an entire process after it finsihes. The problem I have is, I don't know how long the process may take. It may take 2 minutes or it may take 1.5 hours to complete. After it completes, it pops up two windows which I have to click "OK" to. As I want to automate the process I want to completely kill the process so it performs the next step in the .bat file.
This is what I've got so far in the .bat file below. AutoIT and AHK solutions also happily accepted. PLEASE NOTE*** The main application window and the popup windows have the same name which is "AutoMe".
#echo off
:: this is the long running process
am -a arobot
:: I was hoping this would kill the process but it just gets stuck with a
:: messagebox
taskkill /F /IM am.exe
:: Next step to perform
sqlldr XXXXXX
pause
Here is two AutoIt solutions.
If you don't need to click the two okay buttons before your kill the process.
While 1
Sleep(250)
If WinExists("Title of the window with the OK button") Then ExitLoop
WEnd
;Close process. Make sure that am.exe is the process name.
ProcessClose("am.exe")
If you need to click the two okay buttons before your kill the process.
While 1
Sleep(250)
If WinExists("Title of the window with the OK button") Then ExitLoop
WEnd
$hWnd = WinGetHandle("Title of the window with the OK button")
WinActivate($hWnd)
WinWaitActive($hWnd)
ControlClick("My Window", "", "[CLASS:Button; TEXT:OK; INSTANCE:1]") ;<<<check to make sure you have the right button control
WinWait("title of second window")
$hWnd = WinGetHandle("title of second window")
WinActivate($hWnd)
WinWaitActive($hWnd)
ControlClick("My Window", "", "[CLASS:Button; TEXT:OK; INSTANCE:1]") ;<<<check to make sure you have the right button control
;Close process. Make sure that am.exe is the process name.
ProcessClose("am.exe")
When the pop upwindow has the same name as the main window you can look for the ok button control or any other control in that window instead of the window title.
While 1
Sleep(250)
If ControlCommand("win title", "", "[CLASS:Button; TEXT:OK; INSTANCE:1]", "IsVisible", "") = 1 Then ExitLoop
WEnd
Another alternative is checking for the window handle. When you use WinGetHandle and there is two windows with the same name it will get the handle of the most recently active window. In your case you can use this feature to see when the popup window comes up.
$hWnd = WinGetHandle("Window title")
While 1
Sleep(250)
If $hWnd <> WinGetHandle("Window title") Then ExitLoop
WEnd
You can use the AutoIt Window Information Tool to find the controls and window titles.
Start the process in background and wait for a window with the specified title Some Window Title:
#echo off
start "" /b am -a arobot
:wait
timeout 1 >nul
for /f "tokens=2" %%a in ('
tasklist /fi "windowtitle eq Some Window Title" /fo list ^| find "PID:"
') do (
taskkill /f /pid %%a
goto next
)
goto wait
:next
sqlldr XXXXXX
pause

Chrome Extension - Message Passing to batch file

I used the sample project
https://developer.chrome.com/extensions/samples
I am able to run the python native app.
Is there any way to get the message within native-messaging-example-host.bat
I don't want to load python script
What I want to do here is
send message from chrome {text: "xyz.bat"}
and the batch file should run START xyz.bat
You should not approach this problem from the batch file standpoint, as in lieu of my solution, it requires the program to be run upfront, which in most applications is depreciated in favor of running it in the background. However if you still want to know how you could potentially do it in batch...
If you can pass the message to a blank html page (not currently sure how you can or want to do it this way), where the only thing on that html page is your runme.bat we can run a program that would copy the page, open a text file and paste it inside, close the text file, and run the batch with input from it. So code wise,
#if (#CodeSection == #Batch) #then
#echo off
set SendKeys=CScript //nologo //E:JScript "%~F0"
rem below copys everything on the page, and closes it
%SendKeys% "{TAB}"
%SendKeys% "^{A}"
%SendKeys% "^{C}"
%SendKeys% "^{W}"
rem open text file,wait for it load, paste clipboard, save and exit
start newreadforme.txt
timeout /nobreak /t 5
%SendKeys% "^{V}"
%SendKeys% "^{S}"
timeout /nobreak /t 2
%SendKeys% "^{W}"
start program.bat
goto :EOF
#end
// JScript section
var WshShell = WScript.CreateObject("WScript.Shell");
WshShell.SendKeys(WScript.Arguments(0));
then in your batch file
#echo off
set /p x=<newreadforme.txt
start %x%
This code will run simulated keystrokes on the opened page to copy its contents and relay to a text file to be referenced from another batchfile. But you should only use this method as a last resort as this approach is a TERRIBLE way to solve your problem. My code requires you to keep the webpages open and upfront and make sure no one interferes with the program during its execution. So if a user is using the computer the time its running, then they may accidentally mess with the inputs.
On top of that, already you need to be modifying webpages to achieve your end result so you probably should use a language that supports html to filesystem operations. Nodejs can provide a nice interface between the file system and html pages that you may decide to pass. How you handle the webpage filled with the message i am not sure of but you should most certainly avoid using batch to do what you ask in favor of more html friendly languages

CMD: Set buffer height independently of window height

I've recently learned that I can control the size of the CMD window running my program with mode x,y. However I just as recently noticed that this sets the buffer size, and the window will adjust to match or max out at the screen size.
I would like to use mode 100,50 for the window size, but I also want to keep a arger buffer - for development at least I want mode 100,9999.
Is there any way to do this?
I don't think there is a native batch command that gives independent control of buffer and window sizes. .NET can control both, but I don't think VBScript or JScript can access that functionality. But powershell can :-) See How Can I Expand the Width of the Windows PowerShell Console?
Thankfully, the new settings are preserved in the CMD window when PowerShell exits.
It is important that the window size is always less than or equal to the buffer size. To simplify things, I first use MODE to set both the window and buffer to the desired window size, and then I use powershell to set the buffer size.
Here is a simple conSize.bat hybrid batch/powershell script that takes the sizes as parameters:
#echo off
:conSize winWidth winHeight bufWidth bufHeight
mode con: cols=%1 lines=%2
powershell -command "&{$H=get-host;$W=$H.ui.rawui;$B=$W.buffersize;$B.width=%3;$B.height=%4;$W.buffersize=$B;}"
To get your desired size, you would simply use
call conSize 100 50 100 9999
There's a 'ConSetBuffer' binary available that does specifically this, and I've found it to work reliably. It and related console utilities are available at the 'conutils.zip' link on this page.
I have written a tiny application for Windows that allows to "maximize" the window and buffer. It could be easily extended to allow passing parameters with custom values.
here another variant:
/*
#echo off & mode 100,50
set "cscfile="
set Pathfile="%WinDir%\Microsoft.NET\Framework\csc.exe"
for /f "delims=" %%a in ('dir /b /a-d /s %PathFile%') do set "cscfile=%%a"
if defined cscfile (
%cscfile% /nologo /out:"%~0.exe" %0
) else exit /b
"%~0.exe"
del "%~0.exe"
cmd /k
*/
using System;
class Program
{
static void Main()
{
Console.SetBufferSize(100, 9999);
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Current Logged UserName: " + Environment.UserName);
Console.ResetColor();
Console.WriteLine("[Enter] to continue");
Console.ReadLine();
}
}
The answer to this question didn't work as I got an error regarding variables sent to the PowerShell command, so I modified to work.
The PowerShell command simply adds uiHeightBuffer to the uiHeight variable to show the scroll bar.
Edit: Added the height buffer as the 3rd parameter and TRUE or FALSE as a 4th parameter to enable or disable the scrollbar.
I found this useful when exiting a script with a small message when there's no need for the scrollbar in this case.
Also to enable UTF-8 encoding you have to set the default at the start of the `:CMDSIZE' call and set it at the end, otherwise, the font size goes a bit funny.
Omitting chcp 850 >NUL & and chcp 65001 >NUL & are what you'd do if you didn't want to affect this.
This works in Version: 1909 of Windows 10.
#echo off
title %~nx0
rem Based on this thread here: https://stackoverflow.com/a/13351373
goto MYROUTINE
:CMDSIZE
chcp 850 >NUL & set "uiWidth=%1" & set "uiHeight=%2"
mode %uiWidth%,%uiHeight%
if %4==TRUE (set /a "uiHeightBuffer=uiHeight+%3")
if %4==TRUE (powershell.exe -ExecutionPolicy Bypass -Command "&{$H=get-host;$W=$H.ui.rawui;$B=$W.buffersize;$B.width=%uiWidth%;$B.height=%uiHeightBuffer%;$W.buffersize=$B}")
if %4==FALSE (powershell.exe -ExecutionPolicy Bypass -Command "&{$H=get-host;$W=$H.ui.rawui;$B=$W.buffersize;$B.width=%uiWidth%;$B.height=%uiHeight%;$W.buffersize=$B}")
chcp 65001 >NUL & goto :EOF
:MYROUTINE
call :CMDSIZE 255 44 222 TRUE
title Do your routine here...
echo Do your routine here...
echo/ & pause
goto :EXITROUTINE
:EXITROUTINE
call :CMDSIZE 40 2 0 FALSE
title Exiting routine message...
echo Exiting routine message...
set /p "=" <NUL
ping localhost -n 3 >NUL & exit
I have found a way to resize the buffer size without influencing the window size. It works thanks to a flaw in how batch works but it gets the job done.
mode 648 78 >nul 2>nul
How does it work? There is a syntax error in this command, it should be "mode 648, 78". Because of how batch works, the buffer size will first be resized to 648 and then the window resize will come but it will never finish, because of the syntax error. Voila, buffer size is adjusted and the window size stays the same. This produces an ugly error so to get rid of it just add the ">nul 2>nul" and you're done.

Need to Run Windows Security Dialog Box from Command Line

You know, what you normally get when typing ctrl-alt-del or ctrl-alt-end. Except in this scenario I can't press those keys, but I want to launch that box. Specifically I want to be able to pull up the change password dialog from the command line.
Thanks
Here is an extension of the answer given by Raymond Chen. I shows how to call the WindowsSecurity from a batch file. Note that it will only work properly when connected by a terminal session to Microsoft Terminal Server.
#if (#CodeSection == #Batch) #then
#echo off
:: See https://gist.github.com/DavidRuhmann/5199433 and
:: http://msdn.microsoft.com/en-us/library/windows/desktop/gg537748%28v=vs.85%29.aspx
:: for details.
CScript //E:JScript //Nologo "%~0" %*
exit /b
#end
try
{
var objShell = new ActiveXObject("shell.application");
objShell.WindowsSecurity();
WScript.Quit(0);
}
catch(e)
{
WScript.Quit(1);
}
You call the Shell.WindowsSecurity method. The documentation includes sample code.
OSK.exe will bring up an on screen keyboard. It should allow you to hit ctrl-alt-del
control.exe password.cpl - will launch the password Control Panel applet.

Resources