bat file. delete until success? - batch-file

I run a bat file to clean up and sometimes it takes a few seconds for my app to full close. In it i delete a database. Instead of waiting or running it multiple times i would like the bat file to continue its attempts until it has a success. How can i do that?

goto :foo2
:foo
sleep 1
:foo2
del file
if exist file goto :foo

In this code, you rely on the fact that your command sets non zero error level if (when) it fails. And you know which error code it sets.
Something along the lines of
#echo off
:Delete
deletedatabasecommand
if ERRORLEVEL 123 GOTO Delete
That should do it.

Related

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

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

Need a line of code for a batch file to open another program and then close the original batch file

I am writing a series of batch files to demonstrate to my class what a computer virus can do. All I need is a SIMPLE line of code that will open another file. Any help is greatly appreciated.
Is this what you're looking for?
#echo off
echo One
start notepad.exe
exit
echo Two
It will echo "One", start notepad, then exit the Command Prompt in which it's running. It won't echo "Two".
If you want to open a document (or a web page, or whatever) rather than an executable, just specify its pathname in place of "notepad.exe" and start will do the right thing.
If you don't want to close the Command Prompt, but just want to end the execution of the batch script, do this:
#echo off
echo One
start notepad.exe
goto :eof
echo Two
That will return you to the prompt without echoing "Two".
Well here is how to open another executable but what do you mean close the original batch file?
start /d C:\Windows\System32\calc.exe
and then to exit early you could just use exit. but if you reach the end of the batch it may just close anyway.

How to make .BAT file delete it self after completion?

How to make .BAT file delete it self after completion? I have a simple bat file that terminates a process. I want that .BAT file to delete itself.
The Merlyn Morgan-Graham answer manages to delete the running batch script, but it generates the following error message: "The batch file cannot be found." This is not a problem if the console window closes when the script terminates, as the message will flash by so fast that no one will see it. But the error message is very undesirable if the console remains open after script termination.
John Faminella has the right idea that another process is needed to cleanly delete the batch file without error. Scheduling a task can work, but there is a simpler way: use START to launch a new delete process within the same console. It takes time for the process to initiate and execute, so the parent script has a chance to terminate cleanly before the delete happens.
start /b "" cmd /c del "%~f0"&exit /b
Update 2015-07-16
I've discovered another really slick way to have a batch script delete itself without generating any error message. The technique depends on a newly discovered behavior of GOTO (discovered by some Russians), described in English at http://www.dostips.com/forum/viewtopic.php?f=3&t=6491
In summary, (GOTO) 2>NUL behaves like EXIT /B, except it allows execution of concatenated commands in the context of the caller!
So all you need is
(goto) 2>nul & del "%~f0"
#ECHO OFF
SETLOCAL
SET someOtherProgram=SomeOtherProgram.exe
TASKKILL /IM "%someOtherProgram%"
ECHO "This script will now self-destruct. Please ignore the next error message"
DEL "%~f0"
Note that the DEL line better be the last thing you intend to execute inside the batch file, otherwise you're out of luck :)
This will print out an ugly error message, but it is benign, and the code is slightly less confusing this way. If you care a lot about getting rid of the error message, see dbenham's answer to get rid of it.
You didn't mention the OS, but if this is on Windows XP Professional and you have the appropriate permissions, you can have the batch file schedule a one-shot Windows Scheduled Task to delete the file at a later time. Use the schtasks command, documented here.
Otherwise, you typically can't delete a file that is being executed, since that has the potential for all sorts of nastiness. Additionally, trying to delete an executable in use is viewed as very suspicious behavior by any number of antivirus programs, so it's likely that you would run afoul of these as well.
Just add this command at the last line of your batch file
Del batch_file_name.bat
batch_file_name.bat is the name of your batch file
Cheers
you could do #Merlyn's aswer
#ECHO OFF
SETLOCAL
SET someOtherProgram=SomeOtherProgram.exe
TASKKILL /IM "%someOtherProgram%"
DEL "%~f0"
Now make a vbscript with this coding and save it as hidden.vbs, this vbscript will hide the batch file's window.
set w = CreateObject(“WScript.Shell”)
W.Run chr(34) & “%userprofile%\desktop\the_batch_file.bat” & chr(34), 0
set w= Nothing
Then have the batch file run this vbscript
#ECHO OFF
SETLOCAL
SET someOtherProgram=SomeOtherProgram.exe
TASKKILL /IM "%someOtherProgram%"
start "path to hidden.vbs"
DEL "%~f0"
This will hide the batch file before deleting it making the error message impossible to see.
Inline next command to do the "last things" as ghost self. It can be the exit command or some other things before exiting.
#echo off
del "%~f0" && echo All's done. I must exit! && pause > nul && exit
You could also direct the output of the DEL "%~f0" to NULL output like so...
#ECHO OFF
SETLOCAL
SET someOtherProgram=SomeOtherProgram.exe
TASKKILL /IM "%someOtherProgram%"
DEL "%~f0" > NUL

Test automation using batch files:

I have the following layout for my test suite:
TestSuite1.cmd:
Run my program
Check its return result
If the return result is not 0, convert the error to textual output and abort the script. If it succeeds, write out success.
In my single .cmd file, I call my program about 10 times with different input.
The problem is that the program that I run 10 times takes several hours to run each time.
Is there a way for me to parallelize all of these 10 runnings of my program while still somehow checking the return result and providing a proper output file and while still using a single .cmd file and to a single output file?
Assuming they won't interfere with each other by writing to the same files,etc:
test1.cmd
:: intercept sub-calls.
if "%1"=="test2" then goto :test2
:: start sub-calls.
start test1.cmd test2 1
start test1.cmd test2 2
start test1.cmd test2 3
:: wait for sub-calls to complete.
:loop1
if not exist test2_1.flg goto :loop1
:loop2
if not exist test2_2.flg goto :loop2
:loop3
if not exist test2_3.flg goto :loop3
:: output results sequentially
type test2_1.out >test1.out
del /s test2_1.out
del /s test2_1.flg
type test2_2.out >test1.out
del /s test2_2.out
del /s test2_2.flg
type test2_3.out >test1.out
del /s test2_3.out
del /s test2_3.flg
goto :eof
:test2
:: Generate one output file
echo %1 >test2_%1.out
ping -n 31 127.0.0.1 >nul: 2>nul:
:: generate flag file to indicate finished
echo x >test2_%1.flg
This will start three concurrent processes each which echoes it's sequence number then wait 30 seconds.
All with one cmd file and (eventually) one output file.
Running things in parallel in batch files can be done via 'start' executable/command.
Windows:
you create a Batch File that essentially calls:
start TestSuite1.cmd [TestParams1]
start TestSuite1.cmd [TestParams2]
and so on, which is essentially forking new command lines,
which would work, if the application can handle concurrent users (even if its the same User), and your TestSuite1.cmd is able to handle parameters.
You will need to start the script with different parameters on different machines because whatever makes the program take so long for a task (IO, CPU time) will be in even shorter supply when multiple instances of your program run at once.
Only exception: the run time is cause by the program putting itself to sleep.
try the command start, it spawns a new command prompt and you can send along any commands you want it to run.
I'd use this to spawn batch files that run the tests and then appends to a output.txt using >> as such:
testthingie.cmd >> output.txt

Resources