How to evaluate exit code of an application started from within a batch file? - batch-file

I am trying to execute an application from a batch file by using START command (to hide console when executing) and I need to get errorlevel after execution. For example after System.exit(10) I'd like to restart Java application:
:while
START javaw ...
IF errorlevel 10 GOTO while
But it doesn't work because errorlevel condition is evaluated before the java process has finished.
I've also tested the next code but I get an empty text file because of the same reason:
:while
start javaw ... >exit.txt 2>&1
set /p status=<exit.txt
if "%status%"=="10" goto :while
Then, is there any way to launch a Java application, without console (/WAIT is not an option), and using a loop to restart the app when a problem occurs?

See answer on question How to call a batch file in the parent folder of current batch file? to understand the 4 different methods on running an application or batch file from within a batch file.
And see also Difference between java/javaw/javaws.
The execution of the batch file results already in opening a console window.
Therefore I suggest to use simply
:while
java.exe ...
IF errorlevel 10 GOTO while
Or use following code if you don't want to see any output by the Java application in console window of the batch file:
:while
java.exe ... 1>nul 2>nul
IF errorlevel 10 GOTO while
1>nul redirects output written to stdout to device NUL and 2>nul redirects the error messages written to stderr also to device NUL.
The only solution I can think of running a Java application without displaying a console window and additionally check successful execution of the Java application would be to write a Windows (GUI) application in C/C++/C# which does not open a window like javaw.exe and which runs javaw.exe with the appropriate parameters as process with evaluating the return code.
But with a batch file it is impossible to avoid opening a console window completely as far as I know. The console window can be opened minimized, but not hidden completely.

using this solution: Windows batch assign output of a program to a variable you can do something like this:
#echo off
:loop
application arg0 arg1 > temp.txt
set /p status=<temp.txt
if "%status%"=="10" goto :loop
echo "Done."

Related

Combine Windows CMD BAT files

I'm trying to build a .bat file that will run an executable Java SpringBoot web app jar file (keeping the cmd window open so that I can verify it started cleanly and close it/kill the process when I'm done), then wait 10 seconds to give the app time to start, then finally open it's URL in my web browser.
I've been able to get my intended functionality by breaking it down into two .bat files. The code I have below does what I want (except the echo message is repeated, but that's not a big deal).
I'd like to know how I can achieve the same functionality within a single .bat file.
I have launch.bat:
start wait.bat
java -jar C:\dev_tools\myapp.jar
which calls wait.bat:
echo Waiting for app to start before launching browser...
timeout 10
start http://localhost:8013/myapp/ && exit
Given the combined script is called launch.bat, put if not "%~1" == "" goto :JUMP on top, then the contents of launch.bat but with the first line changed to start launch.bat #, then place goto :EOF, then :JUMP, then the contents of wait.bat:
if not "%~1" == "" goto :JUMP
start launch.bat #
java -jar C:\dev_tools\myapp.jar
goto :EOF
:JUMP
echo Waiting for app to start before launching browser...
timeout 10
start http://localhost:8013/myapp/ && exit
When you now start launch.bat, it first checks if there is an argument, which should not be the case initially; so the first start command line is reached where the script executes itself, but with an argument (#) this time; the initially executed instance continues executing the rest until goto :EOF is reached, which terminates execution.
The recursively called instance will immediately continue execution at label :JUMP, where the code of the original wait.bat script is placed.
I think, this should work:
#echo off
start "MyApp" java.exe -jar C:\dev_tools\myapp.jar
echo Waiting for app to start before launching browser...
%SystemRoot%\System32\timeout.exe 10
start http://localhost:8013/myapp/
java.exe is started as separate process running parallel to cmd.exe instance processing this batch file.
So immediately after starting java.exe the information line is output by cmd.exe in initially opened console window.
Then timeout is executed to wait 10 seconds before finally the application is started with the HTTP URL.
Finally cmd.exe finishes processing the batch file as reading end of batch file which results in terminating the cmd.exe if started with option /C as done on double clicking on a batch file.
The Java application started as separate process keeps running independent on termination of cmd.exe processing the batch file.
I hope this is what you want.
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.
echo /?
start /?
timeout /?

Why does command START used in a batch file not start a batch file?

I made a Main batch file with the lines below:
#echo off
color 1e
title ------ Just a Test ------
start "C:\Users\%USERNAME%\Desktop\Check.bat"
:START
echo Welcome to the Game!
...
And Check.bat contains:
#echo off
if not exist "C:\Users\%USERNAME%\Desktop\Batch_System\importantFile.dll" goto ERROR
if exist "C:\Users\%USERNAME%\Desktop\Batch_System\importantFile.dll" goto CONTINUE
:ERROR
cls
echo ERROR :
echo Important file not found. please reinstall the program
pause
exit /b
:CONTINUE
cls
exit /b
When I use the command start, it starts only a command prompt with the Check.bat directory and the main batch file continues executing the game. I want to force close the main batch file if importantFile.dll doesn't exist.
Okay, let me explain: When the main batch file is executed and runs the command start to start another batch file called Check.bat, the file Check.bat checks if the file importantFile.dll exists, and if not, Check.bat displays an error message.
Does anyone know how to write Check.bat in a manner that when the .dll file does not exist, force the main batch file to exit?
First, help on every command can be get by running in a command prompt window the command with /? as parameter. start /? outputs the help of command START. call /? outputs the help of command CALL usually used to run a batch file from within a batch file. Those two commands can be used to run a batch file as explained in detail in answer on How to call a batch file that is one level up from the current directory?
Second, the command line
start "C:\Users\%USERNAME%\Desktop\Check.bat"
starts a new command process in foreground with a console window with full qualified batch file name as window title displayed in title bar at top of the console window. That is obviously not wanted by you.
Third, the Wikipedia article Windows Environment Variables lists the predefined environment variables on Windows and their default values depending on version of Windows.
In general it is better to use "%USERPROFILE%\Desktop" instead of "C:\Users\%USERNAME%\Desktop".
There is no C:\Users on Windows prior Windows Vista and Windows Server 2008 by default at all.
The users profile directory can be on a different drive than drive C:.
It is also possible that just the current user's profile directory is not in C:\Users, for example on a Windows server on which many users can logon directly and for which the server administrator decided to have the users' profile directories on a different drive than system drive making backup and cleaning operations on server much easier and is also better for security.
Well, it is also possible to have the user's desktop folder not in the user's profile directory. But that is really, really uncommon.
Fourth, on shipping a set of batch files, it is recommended to use %~dp0 to call other batch files from within a batch file because of this string referencing drive and path of argument 0 expands to full path of currently executed batch file.
The batch file path referenced with %~dp0 always ends with a backslash. Therefore concatenate %~dp0 always without an additional backslash with another batch file name, folder or file name.
See also What is the reason for batch file path referenced with %~dp0 sometimes changes on changing directory?
Fifth, I suggest following for your two batch files:
Main.bat:
#echo off
color 1e
title ------ Just a Test ------
call "%~dp0Check.bat" || color && exit /B
echo Welcome to the Game!
Check.bat:
#echo off
cls
if exist "%~dp0Batch_System\importantFile.dll" exit /B 0
echo ERROR:
echo Important file not found. Please reinstall the program.
echo/
pause
exit /B 1
The batch file Check.bat is exited explicitly on important file existing with returning exit code 0 to the parent batch file Main.bat. For that reason Windows command processor continues execution of Main.bat on the command line below the command line calling the batch file Check.bat.
Otherwise Check.bat outputs an error message, waits for a pressed key by the user and exits explicitly with non zero exit code 1. The non zero exit code results in Main.bat in executing the next command after || which is COLOR to restore initial colors and next executing also EXIT with option /B to exit the execution of Main.bat.
See also:
Single line with multiple commands using Windows batch file
What are the ERRORLEVEL values set by internal cmd.exe commands?
Which cmd.exe internal commands clear the ERRORLEVEL to 0 upon success?
Where does GOTO :EOF return to?
exit /B without an additionally specified exit code is like goto :EOF.
The CALL command line in Main.bat could be also written as:
call "%~dp0Check.bat" || ( color & exit /B )
And Main.bat could be also written as:
#echo off
color 1e
title ------ Just a Test ------
call "%~dp0Check.bat"
if errorlevel 1 (
color
goto :EOF
)
echo Welcome to the Game!
I do not recommend using in Main.bat just EXIT instead of exit /B or goto :EOF. Just EXIT would result in exiting the current command process independent on calling hierarchy and independent on how the command process was started: with option /K to keep it running to see error messages like on opening a command prompt window and next running a batch file from within command prompt window, or with /C to close the command process after application/command/script execution finished like on double clicking on a batch file.
It is advisable to test batch files by running them from within an opened command prompt window instead of double clicking on them to see error messages on syntax errors output by cmd.exe. For that reason usage of just EXIT is counter-productive for a batch file in development. Run cmd /? in a command prompt window for help on Windows command processor itself.
Last but not least see:
Microsoft's command-line reference
SS64.com - A-Z index of the Windows CMD command line
start is asynchronous by default. Use start /wait so that main.bat can test the exit code of check.bat. Make check.bat return an appropriate exit code.
For example...
main.bat
#echo off
start /b /wait check.bat
if not %errorlevel% == 0 exit /b
echo "Welcome to the game!"
...
check.bat
#echo off
if exist "importantfile.dll" exit 0
echo ERROR: Important file not found. Please reinstall the program.
pause
exit 1
notes
Added /b to start to avoid opening another window. Change that per your preference.
You could use call instead of start but call gives the called code access to the variables of main.bat so encapsulation is improved if you use start as you did.
The logic in check.bat is simplified above. Once you identify the success path early in the script and exit, the rest of the script can assume the fail path. This saves you a few if's and labels which you might find simplifies writing and reading of similar scripts. Beware of potentially confusing multiple exit points in longer scripts though!
When choosing exit codes, 0 is a common convention for success.
The above code is just one technique - there are several other options (such as checksomething && dosomethingifok). Some useful information on return codes, and checking them, can be found in http://steve-jansen.github.io/guides/windows-batch-scripting/part-3-return-codes.html
Thanks to the answer from Mofi. I've my example and exp. on this. To be short, it's about the setting of log date format. You may change the format of time , date and log. you may have the result.
why-batch-file-run-with-failure-in-windows-server

Need Batch file help searching for specific string being created in another rolling open session?

Thanks. Thought I'd try writing a batch file to kill another open cmd session that is constantly open churning out lots of scrolling info.
I got a bit carried away and am now outta my league so to speak.
Basically I am trying to search for "£000.00" within a each emerging line of tet that appears in the other running open command window. The running command session is named in the window as C:\windows\system32\cmd.exe but is does have a valid .exe process name in task manager while running and open.
The batch file code below is as far as I've got.
The idea is that when the above string is found in the other process that process/program get closed down them re-launched.
This is as far as I've got.
#echo off
#echo off
title Shut down other process and relaunch
:loop
start /d "C:\Users\Desktop" ActiveDOSprogram.exe
:: #setlocal enabledelayedexpansion
:: #echo off
:: set stringfound=1
find /c "*£000.00*" C:\Windows\system32\cmd.exe && (echo found %date% %time%:~0,-3% >> "%USERPROFILE%\Desktop\Crash_Report.txt"
taskkill /IM ActiveDOSprogram.exe /F
timeout /t 20
start /d "C:\Users\Desktop" ActiveDOSprogram.exe
goto loop
So when I tried this without any variables and in a loop and I think i nearly blew my PC!
Reason I'm stuck is I'm really a novice at this (but trying) and I got as far as I think I need a variable in there somewhere, that only move's to the next line (taskkill+restart) when £000.00 is found in the other process.
Thanks
wingman

Why do not all started applications save the wanted information in the text files as expected?

I am trying to create a batch file on a USB drive that will run an .exe, save its text to a .txt file, and then close the .exe.
I am currently running into a weird problem, only 5 of the 18 .exe's are actually saving their text to a file.
This is the convention I am using to complete my task:
start IEPassView.exe /stext Results/IEPassView.txt
taskkill /f /im IEPassView.exe
start MailPassView.exe /stext Results/MailPassView.txt
taskkill /f /im MailPassView.exe
start MessenPass.exe /stext Results/MessenPass.txt
taskkill /f /im MessenPass.exe
start RouterPassView.exe /stext Results/RouterPassView.txt
taskkill /f /im RouterPassView.exe
start ProtectedStoragePassView.exe /stext Results/ProtectedStoragePassView.txt
taskkill /f /im ProtectedStoragePassView.exe
start DialUpPassView.exe /stext Results/DialUpPassView.txt
taskkill /f /im DialUpPassView.exe
I have 18 of the above blocks in a row all calling different small programs and even though 5 of them actually save the files none of them save a .cfg file as they sometimes do. Any help would be greatly appreciated, thanks.
There are mainly 3 different types of executables:
A console application is reading from stdin or a file and writing to stdout or a file and outputs error messages to stderr.
The processing of a batch file is halted on starting a console application until the console application terminated itself. The correct term is therefore: calling a console application.
The exit code of the console application is assigned to environment variable ERRORLEVEL and can be also directly evaluated for example with if errorlevel X rem do something
Many *.exe in System32 directory of Windows are such console applications, like find.exe, findstr.exe, ping.exe, ...
A GUI (graphical user interface) application is started as new process which means the Windows command processor does not halt batch processing until the GUI application terminates itself.
It is not easily possible to get something from within a command process from such applications. GUI applications are designed for interacting via a graphical user interface with a user and not via standard streams or files with a command process.
A typical example for such applications is Windows Explorer explorer.exe in Windows directory.
A hybrid application supports both interfaces and can be therefore used from within a command process as well as by a user via GUI.
Hybrid applications are rare because not easy to code. The behavior of hybrid applications on usage from within a batch file must be find out by testing.
Example for such applications are Windows Registry Editor regedit.exe or shareware archiver tool WinRAR WinRAR.exe.
It is best to look on simple examples to see the differences regarding starting/calling all 3 types of applications from within a batch file.
Example for console application:
#echo off
cls
%SystemRoot%\System32\ping.exe 127.0.0.1 -n 5
echo.
echo Ping finished pinging the own computer (localhost).
echo.
pause
The command processing is halted until ping.exe terminated itself which takes 4 seconds. There is no need for start or call for such applications, except the console application should be intentionally executed in a separate process.
Example for a GUI application:
#echo off
cls
%WinDir%\Explorer.exe
echo.
echo Windows Explorer opened and is still running!
echo.
pause
This batch file outputs the text and message prompt to press any key immediately after starting Windows Explorer indicating that Windows Explorer was started as separate process and Windows command processor immediately continued on the next lines of the batch file. So although Windows Explorer was started and is still running, the batch processing continued, too.
Example for a hybrid application:
#echo off
cls
"%ProgramFiles%\WinRAR\WinRAR.exe"
echo.
echo User exited WinRAR.
echo.
pause
This batch file starts WinRAR without any parameter (usually not useful from within a batch file) if being installed at all in default installation directory. But batch processing is halted until the user exited WinRAR for example by clicking on X symbol of the WinRAR´s application window.
But opening a command prompt window and executing from within the window
"%ProgramFiles%\WinRAR\WinRAR.exe"
results in getting immediately the prompt back in command window to type and execute the next command. So WinRAR finds out what is the parent process and acts accordingly.
Windows Registry Editor shows the same behavior. Executing from within a command prompt window
%WinDir%\regedit.exe
results in opening Windows Registry Editor, but next command can be immediately entered in command prompt window. But using this command in a batch file results in halting batch processing until GUI window of Windows Registry Editor is closed by the user.
Therefore hybrid applications are used from within a batch file mainly with parameters to avoid the necessity of user interaction.
Okay, back to the question after this brief lesson about various types of applications.
First suggestion is using
Result\TextFileName.txt
instead of
Result/TextFileName.txt
as the directory separator on Windows is the backslash character, except the executables require forward slashes as directory separator because of being badly ported from Unix/Linux to Windows.
Second suggestion is finding out type of application. Is command start really necessary because the applications don't start itself in a separate process and need user interaction to terminate itself?
Note: Command start interprets first double quoted string as title string. Therefore it is always good to specify as first parameter "" (empty title string) on starting a GUI or hybrid application as a separate process. On starting a console application as a separate process it is in general a good idea to give the console window a meaningful title.
And last if the started applications really would need user interaction to terminate, it would be definitely better to either start and kill them after waiting 1 or more seconds between start and kill or start them all, wait a few seconds and finally kill them all at once.
Example for first solution with starting and killing each application separately:
#echo off
setlocal
set TimeoutInSeconds=3
call :RunApp IEPassView
call :RunApp MailPassView
call :RunApp MessenPass
call :RunApp RouterPassView
call :RunApp ProtectedStoragePassView
call :RunApp DialUpPassView
endlocal
goto :EOF
:RunApp
start "" "%~1.exe" /stext "Results\%~1.txt"
set /A RetryNumber=TimeoutInSeconds + 1
%SystemRoot%\System32\ping.exe 127.0.0.1 -n %RetryNumber% >nul
%SystemRoot%\System32\taskkill.exe /f /im "%~1.exe"
goto :EOF
It is also possible to use timeout instead of ping for the delay if the batch file is only for Windows Vista and later Windows versions.
Example for second solution with starting all applications, wait some seconds and kill them finally all:
#echo off
call :StartApp IEPassView
call :StartApp MailPassView
call :StartApp MessenPass
call :StartApp RouterPassView
call :StartApp ProtectedStoragePassView
call :StartApp DialUpPassView
%SystemRoot%\System32\ping.exe 127.0.0.1 -n 6 >nul
call :KillApp IEPassView
call :KillApp MailPassView
call :KillApp MessenPass
call :KillApp RouterPassView
call :KillApp ProtectedStoragePassView
call :KillApp DialUpPassView
goto :EOF
:StartApp
start "" "%~1.exe" /stext "Results\%~1.txt"
goto :EOF
:KillApp
%SystemRoot%\System32\taskkill.exe /f /im "%~1.exe"
goto :EOF
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 /?
echo /?
endlocal /?
goto /?
ping /?
set /?
setlocal /?
start /?
taskkill /?
See also the Microsoft article about Using command redirection operators.
PS: The last two batch code blocks were not tested by me because of not having available the applications.
I suggest killing all tasks at once, at the end of the very end, possibly after a timeout command with a amount of time appropriate to your system's speed. That may help the issue.

blocking an if statement error message from a batch file

I am trying to design a batch program that scans the D:\ on my computer for a CD album and then opens a program to play it. I don't want to use Autoplay because want to design my own custom program for the purpose. I am using an IF statement and a GOTO statement that loops back to the IF statement after a delay. Here is what I have:
:rescan
if exist D:\Track01.cda start (my soon-to-be music playing program)
timeout 2 /NOBREAK
goto rescan
The problem is that if there is no CD in the drive, the IF statement causes a seprate error message window to pop up.
Is there any way to block this message?
I do not think there is a way to block this message as it is occurring outside of the control of your batch file. However I checked the existence of the drive before entering the loop and this seemed to work for my tests.
IF EXIST D:\ GOTO rescan
echo Drive does not exist
goto end
:rescan
if exist D:\Track01.cda echo start (my soon-to-be music playing program)
timeout 6 /NOBREAK
goto rescan
:end
Hope it helps you out.
use another command:
dir D:\track01.cda 1>nul 2>&1 && start (your program)
If there is no disk, dir returns The device is not ready. and an %errorlevel%of 1. If there is a disk, but no audio-disk (no "track01.cda"), dir returns "File not found" and an %errorlevel%of 1
(All output of dir is redirected to nul to keep the screen clear - change that, if you want that output).
&& works as "if previous command was successful then" ("if %errorlevel% is not 0")

Resources