Running Flutter/Dart commands in batch script halts execution [duplicate] - windows

I'm trying to get my commit-build.bat to execute other .BAT files as part of our build process.
Content of commit-build.bat:
"msbuild.bat"
"unit-tests.bat"
"deploy.bat"
This seems simple enough, but commit-build.bat only executes the first item in the list (msbuild.bat).
I have run each of the files separately with no problems.

Use:
call msbuild.bat
call unit-tests.bat
call deploy.bat
When not using CALL, the current batch file stops and the called batch file starts executing. It's a peculiar behavior dating back to the early MS-DOS days.

All the other answers are correct: use call. For example:
call "msbuild.bat"
History
In ancient DOS versions it was not possible to recursively execute batch files. Then the call command was introduced that called another cmd shell to execute the batch file and returned execution back to the calling cmd shell when finished.
Obviously in later versions no other cmd shell was necessary anymore.
In the early days many batch files depended on the fact that calling a batch file would not return to the calling batch file. Changing that behaviour without additional syntax would have broken many systems like batch menu systems (using batch files for menu structures).
As in many cases with Microsoft, backward compatibility therefore is the reason for this behaviour.
Tips
If your batch files have spaces in their names, use quotes around the name:
call "unit tests.bat"
By the way: if you do not have all the names of the batch files, you could also use for to do this (it does not guarantee the correct order of batch file calls; it follows the order of the file system):
FOR %x IN (*.bat) DO call "%x"
You can also react on errorlevels after a call. Use:
exit /B 1 # Or any other integer value in 0..255
to give back an errorlevel. 0 denotes correct execution. In the calling batch file you can react using
if errorlevel neq 0 <batch command>
Use if errorlevel 1 if you have an older Windows than NT4/2000/XP to catch all errorlevels 1 and greater.
To control the flow of a batch file, there is goto :-(
if errorlevel 2 goto label2
if errorlevel 1 goto label1
...
:label1
...
:label2
...
As others pointed out: have a look at build systems to replace batch files.

If we want to open multiple command prompts then we could use
start cmd /k
/k: is compulsory which will execute.
Launching many command prompts can be done as below.
start cmd /k Call rc_hub.bat 4444
start cmd /k Call rc_grid1.bat 5555
start cmd /k Call rc_grid1.bat 6666
start cmd /k Call rc_grid1.bat 5570.

Try:
call msbuild.bat
call unit-tests.bat
call deploy.bat

You are calling multiple batches in an effort to compile a program.
I take for granted that if an error occurs:
1) The program within the batch will exit with an errorlevel;
2) You want to know about it.
for %%b in ("msbuild.bat" "unit-tests.bat" "deploy.bat") do call %%b|| exit /b 1
'||' tests for an errorlevel higher than 0. This way all batches are called in order but will stop at any error, leaving the screen as it is for you to see any error message.

If we have two batch scripts, aaa.bat and bbb.bat, and call like below
call aaa.bat
call bbb.bat
When executing the script, it will call aaa.bat first, wait for the thread of aaa.bat terminate, and call bbb.bat.
But if you don't want to wait for aaa.bat to terminate to call bbb.bat, try to use the START command:
START ["title"] [/D path] [/I] [/MIN] [/MAX] [/SEPARATE | /SHARED]
[/LOW | /NORMAL | /HIGH | /REALTIME | /ABOVENORMAL | /BELOWNORMAL]
[/AFFINITY <hex affinity>] [/WAIT] [/B] [command/program]
[parameters]
Exam:
start /b aaa.bat
start /b bbb.bat

call msbuild.bat
call unit-tests.bat
call deploy.bat

using "&"
As you have noticed executing the bat directly without CALL,START, CMD /C causes to enter and execute the first file and then the process to stop as the first file is finished. Though you still can use & which will be the same as using command1 & command2 directly in the console:
(
first.bat
)&(
second.bat
)& (
third.bat
)&(
echo other commands
)
In a term of machine resources this will be the most efficient way though in the last block you won't be able to use command line GOTO,SHIFT,SETLOCAL.. and its capabilities will almost the same as in executing commands in the command prompt. And you won't be able to execute other command after the last closing bracket
Using CALL
call first.bat
call second.bat
call third.bat
In most of the cases it will be best approach - it does not create a separate process but has almost identical behaviour as calling a :label as subroutine. In MS terminology it creates a new "batch file context and pass control to the statement after the specified label. The first time the end of the batch file is encountered (that is, after jumping to the label), control returns to the statement after the call statement."
You can use variables set in the called files (if they are not set in a SETLOCAL block), you can access directly labels in the called file.
CMD /C, Pipes ,FOR /F
Other native option is to use CMD /C (the /C switch will force the called console to exit and return the control)
Something that cmd.exe is doing in non transparent way with using FOR /F against bat file or when pipes are used.
This will spawn a child process that will have all the environment ot the calling bat.
Less efficient in terms of resources but as the process is separate ,parsing crashes or calling an EXIT command will not stop the calling .bat
#echo off
CMD /c first.bat
CMD /C second.bat
::not so different than the above lines.
:: MORE,FINDSTR,FIND command will be able to read the piped data
:: passed from the left side
break|third.bat
START
Allows you more flexibility as the capability to start the scripts in separate window , to not wait them to finish, setting a title and so on. By default it starts the .bat and .cmd scripts with CMD /K which means that the spawned scripts will not close automatically.Again passes all the environment to the started scripts and consumes more resources than cmd /c:
:: will be executed in the same console window and will wait to finish
start "" /b /w cmd /c first.bat
::will start in a separate console window and WONT wait to be finished
:: the second console window wont close automatically so second.bat might need explicit exit command
start "" second.bat
::Will start it in a separate window ,but will wait to finish
:: closing the second window will cause Y/N prompt
:: in the original window
start "" /w third.cmd
::will start it in the same console window
:: but wont wait to finish. May lead to a little bit confusing output
start "" /b cmd /c fourth.bat
WMIC
Unlike the other methods from now on the examples will use external of the CMD.exe utilities (still available on Windows by default).
WMIC utility will create completely separate process so you wont be able directly to wait to finish. Though the best feature of WMIC is that it returns the id of the spawned process:
:: will create a separate process with cmd.exe /c
WMIC process call create "%cd%\first.bat","%cd%"
::you can get the PID and monitoring it with other tools
for /f "tokens=2 delims=;= " %%# in ('WMIC process call create "%cd%\second.bat"^,"%cd%" ^|find "ProcessId"') do (
set "PID=%%#"
)
echo %PID%
You can also use it to start a process on a remote machine , with different user and so on.
SCHTASKS
Using SCHTASKS provides some features as (obvious) scheduling , running as another user (even the system user) , remote machine start and so on. Again starts it in completely separate environment (i.e. its own variables) and even a hidden process, xml file with command parameters and so on :
SCHTASKS /create /tn BatRunner /tr "%cd%\first.bat" /sc ONCE /sd 01/01/1910 /st 00:00
SCHTASKS /Run /TN BatRunner
SCHTASKS /Delete /TN BatRunner /F
Here the PID also can acquired from the event log.
ScriptRunner
Offers some timeout between started scripts. Basic transaction capabilities (i.e. rollback on error) and the parameters can be put in a separate XML file.
::if the script is not finished after 15 seconds (i.e. ends with pause) it will be killed
ScriptRunner.exe -appvscript %cd%\first.bat -appvscriptrunnerparameters -wait -timeout=15
::will wait or the first called script before to start the second
:: if any of the scripts exit with errorcode different than 0 will try
:: try to restore the system in the original state
ScriptRunner.exe -appvscript second.cmd arg1 arg2 -appvscriptrunnerparameters -wait -rollbackonerror -appvscript third.bat -appvscriptrunnerparameters -wait -timeout=30 -rollbackonerror

To call a .bat file within a .bat file, use
call foo.bat
(Yes, this is silly, it would make more sense if you could call it with foo.bat, like you could from the command prompt, but the correct way is to use call.)

Simplest Way To Run Multiple Batch Files Parallelly
start "systemLogCollector" /min cmd /k call systemLogCollector.bat
start "uiLogCollector" /min cmd /k call uiLogCollector.bat
start "appLogCollector" /min cmd /k call appLogCollector.bat
Here three batch files are run on separate command windows in a minimized state. If you don't want them minimized, then remove /min. Also, if you don't need to control them later, then you can get rid of the titles. So, a bare-bone command will be- start cmd /k call systemLogCollector.bat
If you want to terminate them, then run these commands-
taskkill /FI "WindowTitle eq appLogCollector*" /T /F
taskkill /FI "WindowTitle eq uiLogCollector*" /T /F
taskkill /FI "WindowTitle eq systemLogCollector*" /T /F

Start msbuild.bat
Start unit-tests.bat
Start deploy.bat
If that doesn't work, replace start with call or try this:
Start msbuild.bat
Goto :1
:1
Start unit-tests.bat
Goto :2
:2
Start deploy.bat

Looking at your filenames, have you considered using a build tool like NAnt or Ant (the Java version). You'll get a lot more control than with bat files.

If you want to open many batch files at once you can use the call command. However, the call command closes the current bat file and goes to another. If you want to open many at once, you may want to try this:
#echo off
start cmd "call ex1.bat&ex2.bat&ex3.bat"
And so on or repeat start cmd "call..." for however many files. This works for Windows 7, but I am not sure about other systems.

Your script should be:
start "msbuild.bat"
start "unit-tests.bat"
start "deploy.bat"

Just use the call command! Here is an example:
call msbuild.bat
call unit-tests.bat
call deploy.bat

With correct quoting (this can be tricky sometimes):
start "" /D "C:\Program Files\ProgramToLaunch" "cmd.exe" "/c call ""C:\Program Files\ProgramToLaunch\programname.bat"""
1st arg - Title (empty in this case)
2nd arg - /D specifies starting directory, can be ommited if want the current working dir (such as "%~dp0")
3rd arg - command to launch, "cmd.exe"
4th arg - arguments to command, with doubled up quotes for the arguments inside it (this is how you escape quotes within quotes in batch)

Running multiple scripts in one I had the same issue. I kept having it die on the first one not realizing that it was exiting on the first script.
:: OneScriptToRunThemAll.bat
CALL ScriptA.bat
CALL ScriptB.bat
EXIT
:: ScriptA.bat
Do Foo
EXIT
::ScriptB.bat
Do bar
EXIT
I removed all 11 of my scripts EXIT lines and tried again and all 11 ran in order one at a time in the same command window.
:: OneScriptToRunThemAll.bat
CALL ScriptA.bat
CALL ScriptB.bat
EXIT
::ScriptA.bat
Do Foo
::ScriptB.bat
Do bar

I know I am a bit late to the party, but here is another way. That is, this method should wait until the first one is done, the second, and so on.
start "" /wait cmd.exe /c msbuild.bat
start "" /wait cmd.exe /c unit-tests.bat
start "" /wait cmd.exe /c deploy.bat
The only issue that may come out of using this method, is that with new instances of cmd.exe being spawned, is that Errorlevel checking is kept within in each instance of cmd.exe.
Or..
start "" /wait call msbuild.bat
start "" /wait call unit-tests.bat
start "" /wait call deploy.bat
Hope this helps.

Related

Can I call %COMSPEC% without terminating all Windows batch execution?

Came across this oddity of batch behaviour as part of the build process in our systems that I'm trying to automate in Jenkins pipelines.
To skip to the meat of the problem and why I'm encountering it, the batch file I'm calling is a build generated batch file that must be called prior to another executable within the same command window to set up paths and alike for our executable to build our system. When building as a user this is fine, you just open the cmd console, run the batch, then run the executable. However in Jenkins I have to pass all commands effectively as one batch file to make it call within the same window, unless I want to mess around with configuring all those paths by hand using withEnv or something.
Something along the lines of this in my Jenkins groovy script:
// Option 1 - && operator
bat "env_configuration.bat && env_dependent_exec.exe"
// Option 2 - multi line version
bat """env_configuration.bat
env_dependent_exec.exe
"""
// Option 3 - same using calls, yadda yadda
bat """call env_configuration.bat
call env_dependent_exec.exe
"""
// Option 4 - Place these calls in batch file and call that instead
bat "run_it_all.bat"
As part of the batch file however, for whatever reason, it has this command within it.
%COMSPEC%
exit /b 0
This will call "C:\WINDOWS\system32\cmd.exe" and output the Mircrosoft version and related blurb.e.g:
Microsoft Windows [Version 10.0.19045.2486]
(c) Microsoft Corporation. All rights reserved.
The catch is, calling this executable will immediately end all batch execution. The line "exit /b 0" isn't actually hit, something whoever created this process I assume never realised. After this batch file process completes, all subsequent commands/calls, (Option 1 above is the easiest to repro) are never hit as all batch processing just stops. This is visible directly in cmd itself, you don't need Jenkins to reproduce.
I will probably wind up just find and replacing this line to comment it out or something... but I refuse to believe I can't find some way of stopping %COMSPEC% from ending all execution of whatever batch file calls it. If I were to guess, I would guess that cmd.exe calls EXIT as it finishes and kills all....
For the sake of interest I have tried modifying the batch file in numerous ways to try and see if I can call %COMSPEC% and still get the rest of the batch script to run afterwards.
:: This fails the same way
call %COMSPEC%
exit /b 0
:: This succeeds to run, but spawns another cmd window that doens't print in the original calling batch file output, so doesn't achieve the original goal
start %COMSPEC%
exit /b 0
:: call %COMSPEC% via subroutine also immediately terminates, we never see "echo 2"
call :comspec_call
exit /b 0
:comspec_call
#echo %COMSPEC% echo 1
%COMSPEC%
#echo %COMSPEC% echo 2
I would guess cmd.exe calls the EXIT command flat on termination, hence the process death, but I've yet to find a means to prevent it doing so...
I've checked %COMSPEC% for flags that might just printout and terminate nicely, but any flags I've found that do provide this information, also terminate with EXIT (I think)
Does anyone has any idea how to call this line and continue execution as I assume the original dev intended?
Cheers in advance!
Batch processing doesn’t just stop — you have started another command interpreter, and the one that launched it is waiting for the new instance to terminate. As it doesn’t quit, everything appears to halt and you wind up killing both to get things back to normal.
Create a new batch script that does everything:
:: controller.bat
#echo off
call env_configuration.bat
call some_other.bat
env_dependent_exec.exe
...
Use of the call command causes the command shell to invoke a script using the current interpreter.
Now your Jenkins groovy script should be:
bat controller.bat
(Disclaimer: I don’t know Jenkins, so...)
Thanks to #Duthomhas and #Magoo
The problem here is that a call to %COMSPEC% launches a new command line process that must terminate before the rest of the script can continue. I didn't understand that cmd.exe was spawning a new script that the call script was waiting to terminate.
With a simplified recap:
:: env_configuration.bat
#echo env_configuration before COMSPEC
#%COMSPEC%
#echo env_configuration after COMSPEC
:: controller.bat
#echo controller before env_configuration.bat
#call env_configuration.bat
#echo controller after env_configuration.bat
controller.bat && #echo back in shell
When you run controller.bat the process will output the Microsoft blurb, but halt.
If you enter "exit" at this point it will kick out of the terminal launched with %COMSPEC% and then all following script steps continue.
It appears the original dev needed the user to be in a new subprocess to continue. The final solution to doing as was intended here is:
:: env_configuration.bat
#echo env_configuration before COMSPEC
#call %COMSPEC% /C <whatever_command_or_exec_next>
#echo env_configuration after COMSPEC
:: controller.bat
#echo controller before env_configuration.bat
#call env_configuration.bat
#echo controller after env_configuration.bat
controller.bat && #echo back in shell
Cheers!

Starting a batch file in a new window from a batch file, and keeping the new window open after completion

EDIT: I will try to make it clearer what I actually want.
I have some very long batch files that I want to run in order and only starting after the previous one had completed.
I am trying to control this with a master batch file
I want them starting each in their own window which remains open after completion to look back later
In numerical order:
1.run main batch file
2.open new cmd window
3.run batch file 1
4.waiting for 1 to finish
5.1 finished, keep window open
6.open another new cmd window
7.run batch2
etc
-- original message --
Hi so I have a windows batch file that needs to run other windows batch files sequentially and wait for them to finish before starting the next one.
Something like:
#echo off
setlocal EnableDelayedExpansion
SET RUN="C:first.bat"
start /wait cmd /c %RUN%
SET RUN="C:second.bat"
start /wait cmd /c %RUN%
where first and second for example just echo something like:
#echo off
echo 1st
exit /b 0
When I run this it starts the first script in a new window and keeps the window open after completing like I want, but to progress to the second script I have to close the new cmd window.
How can I make the main batch script start the second.bat without closing the first.bat cmd window?
Thanks
It is a very unusual requirement that
other batch files should not be processed by the cmd.exe instance processing the main batch file, but by other instances of cmd.exe just to have their outputs in a different console window and
keep each other command process running after finishing the processing of the batch file to be able to view their outputs in their console windows and
wait with further processing of main batch file until processing of a batch file finished by the started separate command process, but do not wait for termination of the started other command processes.
The Windows command processor cmd.exe is not designed for a serialized multi-processing of batch files with multiple instances of itself which finally should keep running.
However, here are three batch files which demonstrate that this is possible with one disadvantage explained later.
Main.bat
#echo off & goto Main
:WaitForBatch
start "Run %~nx1" %ComSpec% /D /S /K "(%ComSpec% /D /C "%~1") & title Finished %~n1"
echo Waiting for finished execution of "%~nx1" ...
:CheckBatchRun
%WaitCommand% >nul
%SystemRoot%\System32\tasklist.exe /NH /FI "IMAGENAME eq cmd.exe" /V | %SystemRoot%\System32\find.exe /I "%~nx1" >nul
if errorlevel 1 goto :EOF
goto CheckBatchRun
:Main
setlocal EnableExtensions DisableDelayedExpansion
title Run %~nx0
if exist %SystemRoot%\System32\timeout.exe (
set "WaitCommand=%SystemRoot%\System32\timeout.exe /T 1"
) else (
set "WaitCommand=%SystemRoot%\System32\ping.exe 127.0.0.1 -n 2"
)
call :WaitForBatch "%~dp0First.bat"
call :WaitForBatch "%~dp0Second.bat"
title Finished %~n0
pause
endlocal
First.bat
#echo off
dir %SystemRoot% /B /S
Second.bat
#echo off
dir %SystemRoot%\*.exe
echo/
pause
Main.bat is coded in a manner expecting First.bat and Second.bat in the same directory as Main.bat, but the other batch files can be also in different directories. The current directory on execution of the three batch files can be any directory.
Main.bat first sets up the execution environment for itself which is:
command echo mode turned off and
command extensions enabled and
delayed expansion disabled.
The window title of the console window of cmd.exe processing Main.bat is modified to show Run Main.bat at beginning.
Next is determined if command TIMEOUT is available in which case this command will be used later for a delay of one second (Windows Vista and later Windows client versions) or if command PING must be used for the one second delay (Windows XP).
Then the subroutine WaitForBatch is called the first time with the batch file First.bat.
The subroutine uses the command START to start one more command process in a new console window with window title Run First.bat with ignoring the AutoRun registry string value which by Windows default does not exist.
This second cmd.exe instance keeps running after execution of the command line specified next with the other arguments is finished. The command line for second cmd.exe requires the execution of a third cmd.exe again with ignoring AutoRun registry string value if existing at all to execute the batch file First.bat specified with fully qualified file name. The third cmd.exe instances closes itself on finishing processing of the batch file.
The second cmd.exe changes now the title of its console window to Finished First. Important is here that the batch file extension is not anymore in the window title.
The first cmd.exe instance processing Main.bat continues with batch file processing already after successful start of second cmd.exe. It uses the command to wait one second and then runs TASKLIST to output all running cmd.exe processes with verbose information which is redirected to command FIND to search case-insensitive for the batch file name First.bat.
As long as there is a cmd.exe process running with First.bat, the first cmd.exe continues batch file processing of Main.bat inside subroutine WaitForBatch in a loop with a jump to CheckBatchRun. Otherwise the subroutine is left and processing of Main.bat continues with the second CALL of WaitForBatch with Second.bat.
Finally Main.bat changes also its window title to Finished Main and prompts the user to press any key in case of Main.bat execution was started with a double click on this file in Windows Explorer.
First.bat takes a very long time to finish as thousands of file names must be output into the console window of second cmd.exe. It is possible to click on the X symbol of console window with title Run First.bat to terminate immediately the execution of second and of third cmd.exe which results in first cmd.exe continues with starting two more cmd.exe for processing Second.bat.
It is also possible to interrupt the long running First.bat by pressing Ctrl+C and answer the prompt for termination of batch job with Y (on English Windows) resulting in third cmd.exe stopping really the processing of First.bat and second cmd.exe keeps running showing the output of First.bat and changing the window title of its console window to Finished First. This is detected by first cmd.exe processing Main.bat and it starts the processing of Second.bat.
The disadvantage of this solution is that on pressing Ctrl+C in console window with title Run First.bat while DIR outputs all the file names and pressing now N (on English Windows) results nevertheless in a termination of the batch job. I am not 100% sure why this happens. I have just a supposition for this behavior.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
cmd /?
dir /?
echo /?
endlocal /?
find /?
goto /?
if /?
pause /?
ping /?
setlocal /?
start /?
tasklist /?
timeout /?
title /?

How to run batch files in background while running multiple files in parallel

I am writing a batch file which will execute 4 other batch files in parallel:
#echo off
echo %time%
(
start call s1.bat
start call s2.bat
start call s3.bat
start call s4.bat
) | set /P "="
echo %time%
But this is opening 4 new windows.
Can anyone help, how to avoid opening multiple windows and run all those 4 batch files in background?
Adding /B is on of the option, but I don't to where to add it exactly.
(
start /B call s1.bat
start /B call s2.bat
start /B call s3.bat
start /B call s4.bat
) | set /P "="
Is giving me an error:
The process tried to write to a nonexistent pipe.
As I do not want to use VB or any other script, how to do it in batch?
This is a really interesting problem! It seems that there is some conflict with the redirection handles.
The main script awaits execution of the sub-scripts with the following code (on Windows 10):
(
> nul start "" /B cmd /D /C call s1.bat
> nul start "" /B cmd /D /C call s2.bat
> nul start "" /B cmd /D /C call s3.bat
> nul start "" /B cmd /D /C call s4.bat
) | set /P =""
The > nul redirection prevents any data to be written to the pipe |. It seems as soon as there becomes anything written to the standard output handle STDOUT (1), the main script does no longer wait (and sometimes the error message The process tried to write to a nonexistent pipe. arises, possibly depending on how fast the sub-script(s) execute(s)). However, as soon as the /B is removed, output to STDOUT by the sub-scripts does not affect the behaviour of the main script, which waits for all sub-scripts, and > nul is therefore no longer necessary.
The explicit cmd /C part is necessary because start would otherwise implicitly use cmd /K when starting internal commands like call which leave non-terminated processes cmd.exe behind upon completion of the respective sub-script.
The /D switch just prevents any auto-run commands to become executed.
When you use normal start without /B for running the sub-scripts, a new instance of the command interpreter is started, that is the process cmd.exe, and a new instance of the console window is started as a process conhost.exe.
Now using start /B still creates a new process cmd.exe but it uses the current process conhost.exe.
I do not know what exactly happens in the background and how all these processes interact, but it appears to me that the issue is connected to the lack of conhost.exe processes when using start /B. Maybe conhost.exe is establishing the redirection handles and hence the pipe. Anyway, as long as there is nothing written to the pipe, there is nothing to conflict, so set /P ="" waits for the related handle to become closed.

How to open new cmd window and execute for-loop in it?

I have a test.cmd file with the following command:
call "cmd /c start echo foo && pause"
call "cmd /c start for /l %%x in (0, 1, 2) do python test.py config%%x"
The first command is working fine and shows that the general approach should work. The second one with the for loop gives me troubles.
When I run this command directly in a CMD window (with only one % sign before the iterator), it starts my python script "test.py" in a new CMD window 3 times in a loop as expected.
When I run the same command from my test.cmd (this time with two % of course), the new CMD window pops up and is gone right away. I don't get any error messages and can't get the new window to stay.
I suspect that I need to do some more encoding but I cannot figure out the correct syntax. What must I change to get this for loop to run from my test.cmd?
if you insist on using call, there is another level of parsing, so in a batchfile you have to use:
call "cmd /k start for /l %%%%i in (1,1,10) do echo %%%%i"
(replaced /c with /k to see the output)
try this:
call "cmd /c for /l %x in (0, 1, 2) do #python test.py config%x"
when you execute loops in command prompt you need single percentage symbol.
And you need to remove the start command after the cmd /c because for is internal cmd command. The # is for suppress printing of prompt value on each iteration.
This answer elaborates on the core question stated in the title of your post rather than on the sample code you provided.
To run a for loop in a separate (cmd) window, the start command is needed. In addition, An explicit cmd instance should be given in order to avoid problems with start when calling internal command lines (for instance, parentheses may cause errors), and also to have control over what happens with the new window after the loop has finished.
The following command line runs a for loop in a new cmd window, which remains open after the loop finished (quite helpful for debugging):
start "" /WAIT cmd /K "for /L %%X in (0,1,2) do echo %%X"
Type exit into the new window to close it. To automatically close the new window finally, replace /K by /C.
If you do not want your main (calling) batch script to wait for the loop to finish and the new window to be closed, remove the /WAIT switch. This way the command line is started, but the main script immediately continues executing. This allows you to run multiple for loops in separate windows simultaneously.
This technique is not limited to calling for loops only.

How do I minimize the command prompt from my bat file

I have this bat file and I want to minimize the cmd window when I run it:
#echo off
cd /d C:\leads\ssh
call C:\Ruby192\bin\setrbvars.bat
ruby C:\leads\ssh\put_leads.rb
I want the command window minimized immediately. Any ideas on how to do this?
There is a quite interesting way to execute script minimized by making him restart itself minimised. Here is the code to put in the beginning of your script:
if not DEFINED IS_MINIMIZED set IS_MINIMIZED=1 && start "" /min "%~dpnx0" %* && exit
... script logic here ...
exit
How it works
When the script is being executed IS_MINIMIZED is not defined (if not DEFINED IS_MINIMIZED) so:
IS_MINIMIZED is set to 1: set IS_MINIMIZED=1.
Script starts a copy of itself using start command && start "" /min "%~dpnx0" %* where:
"" - empty title for the window.
/min - switch to run minimized.
"%~dpnx0" - full path to your script.
%* - passing through all your script's parameters.
Then initial script finishes its work: && exit.
For the started copy of the script variable IS_MINIMIZED is set by the original script so it just skips the execution of the first line and goes directly to the script logic.
Remarks
You have to reserve some variable name to use it as a flag.
The script should be ended with exit, otherwise the cmd window wouldn't be closed after the script execution.
If your script doesn't accept arguments you could use argument as a flag instead of variable:
if "%1" == "" start "" /min "%~dpnx0" MY_FLAG && exit
or shorter
if "%1" == "" start "" /min "%~f0" MY_FLAG && exit
Use the start command, with the /min switch to run minimized. For example:
start /min C:\Ruby192\bin\setrbvars.bat
Since you've specified a batch file as the argument, the command processor is run, passing the /k switch. This means that the window will remain on screen after the command has finished. You can alter that behavior by explicitly running cmd.exe yourself and passing the appropriate switches if necessary.
Alternatively, you can create a shortcut to the batch file (are PIF files still around), and then alter its properties so that it starts minimized.
The only way I know is by creating a Windows shortcut to the batch file and then changing its properties to run minimized by default.
Using PowerShell you can minimize from the same file without opening a new instance.
powershell -window minimized -command ""
Also -window hidden and -window normal is available to hide completely or restore.
source: https://stackoverflow.com/a/45061676/1178975
If you want to start the batch for Win-Run / autostart, I found I nice solution here https://www.computerhope.com/issues/ch000932.htm & https://superuser.com/questions/364799/how-to-run-the-command-prompt-minimized
cmd.exe /c start /min myfile.bat ^& exit
the cmd.exe is needed as start is no windows command that can be executed outside a batch
/c = exit after the start is finished
the ^& exit part ensures that the window closes even if the batch does not end with exit
However, the initial cmd is still not minimized.
One way to 'minimise' the cmd window is to reduce the size of the console using something like...
echo DO NOT CLOSE THIS WINDOW
MODE CON COLS=30 LINES=2
You can reduce the COLS to about 18 and the LINES to 1 if you wish.
The advantage is that it works under WinPE, 32-bit or 64-bit, and does not require any 3rd party utility.
If you type this text in your bat file:
start /min blah.exe
It will immediately minimize as soon as it opens the program. You will only see a brief flash of it and it will disappear.
You could try running a script as follows
var WindowStyle_Hidden = 0
var objShell = WScript.CreateObject("WScript.Shell")
var result = objShell.Run("cmd.exe /c setrbvars.bat", WindowStyle_Hidden)
save the file as filename.js
Yet another free 3rd party tool that is capable of minimizing the console window at any time (not only when starting the script) is Tcl with the TWAPI extension:
echo package require twapi;twapi::minimize_window [twapi::get_console_window] | tclkitsh -
here tclkitsh.exe is in the PATH and is one of the tclkit-cli-*-twapi-*.exe files downloadable from sourceforge.net/projects/twapi/files/Tcl binaries/Tclkits with TWAPI/. I prefer it to the much lighter min.exe mentioned in Bernard Chen's answer because I use TWAPI for countless other purposes already.
You can minimize the command prompt on during the run but you'll need two additional scripts: windowMode and getCmdPid.bat:
#echo off
call getCmdPid
call windowMode -pid %errorlevel% -mode minimized
cd /d C:\leads\ssh
call C:\Ruby192\bin\setrbvars.bat
ruby C:\leads\ssh\put_leads.rb
One option is to find one of the various utilities that can change the window state of the currently running console window and make a call to it from within the batch script.
You can run it as the first thing in your batch script. Here are two such tools:
min.exe
http://www.paulsadowski.com/wsh/cmdprogs.htm
cmdow
http://www.commandline.co.uk/cmdow/index.html
Another option that works fine for me is to use ConEmu, see http://conemu.github.io/en/ConEmuArgs.html
"C:\Program Files\ConEmu\ConEmu64.exe" -min -run myfile.bat
try these
CONSOLESTATE /Min
or:
SETCONSOLE /minimize
or:
TITLE MinimizeMePlease
FOR /F %%A IN ('CMDOW ˆ| FIND "MinimizeMePlease"') DO CMDOW %%A /MIN
http://conemu.github.io/en/ConEmuArgs.html download flagged by Virus Total.
May have Malware.

Resources