Batch files may be considered “old hat” by a lot of people (or a complete mystery to the younger ones!) but they are sometimes still the easiest way to execute simple jobs as they have practically no requirements other than a command shell process to run within – yes there is a strong probability that a script could achieve an identical (or at least equivalent) result, but the fact is that it will be more complex and therefore longer to create and administer.
Something that trips up a fair number of people is the difference between double-clicking a .BAT file and scheduling it as a task to run at a certain time, on a trigger or on a schedule – it can seem that the batch file just simply does not run at all, and the return code sent back to the Task Scheduler is often 0x2, “path not found”, even though the file most definitely is there.
When you double-click a .BAT or .CMD file through Explorer, a cmd.exe process is started to provide the environment in which it will run.
The credentials used are your own (or more correctly, inherited from the Explorer process).
The “current working directory” is set to that where the batch file lives.
When the Task Scheduler service starts the same batch file it actually invokes an instance of cmd.exe (as SYSTEM impersonating the user whose credentials are defined in the task) to carry out the process and waits for it to exit with a return code – the current working directory for this process is not that of the batch file, but that of cmd.exe itself.
Now, if your batch file assumes that you launched it through Explorer or from an existing command prompt with the current working directory set to its own location, you can run into problems.
One simple way to verify if your batch file should work as a scheduled task is to call it from an existing cmd.exe process from a different current working directory (such as your profile, or a temp folder).
Be very, very careful if your batch file does any kind of file deletion – especially if wildcards are involved – you do not want to be in the wrong context when doing this (especially not a system folder or your profile!).
The trick is to do some basic error checking at the start and throughout your batch files, and possibly even some rudimentary logging by piping messages to a file.
One simple solution is to have the batch file set the current working directory itself as one of its first tasks.
e.g. cd /d “J:\Batch Jobs\mrsnrub”
(The “/d” switch is used to set the current drive as well as the directory, and the quotation marks are essential if the path contains any spaces.)
An alternative is to have every action explicitly have a fully qualified path, but this can make things a lot harder to read later.
As far as basic error checking goes, it is always wise to check for the existence of essential files before working with them – a simple “if exist” condition can control a single statement (or alternatively “if not exist” can be used to jump to somewhere else in the batch file).
For simple logging, the “>” instruction will start a new log and “>>” will append to it.
Putting the theory together for a simple example:
echo [%date% - %time%] Log start > %temp%\MyBatch.log
if not exist "J:\Batch Jobs\mrsnrub\" goto ERROR1
cd /d "J:\Batch Jobs\mrsnrub"
if exist "GetFiles.txt" ftp –s:GetFiles.txt
echo Unable to locate folder containing FTP script, aborting
echo ERROR – folder not present >> %temp%\MyBatch.log
This isn’t the most flexible of solutions and it doesn’t log success or failure of attempting to launch FTP.EXE with the script file, but hopefully it should serve as an example of how to achieve basic logging and error checking (including piping the current time and date to a log file, as this is often essential).
One last useful tip is to output or log the “last error” as the last action, using the ERRORLEVEL variable within the batch file – 0 is generally used to indicate “no error”:
ECHO Batch file return code: %ERRORLEVEL%
ECHO Batch file return code: %ERRORLEVEL% >> %temp%\MyBatch.log
One of the best friends you have for debugging batch files is Process Monitor – this lets you verify your batch file (as a cmd.exe process, remember) and lets you see what it was trying to do, along with the results, in particular the Tools / Process Tree view is of great value when looking at the parent/child relationship between processes (ensure to uncheck the “Only show processes still running at the end of current trace” option).
There is a lot more power to batch file programming, this is just scratching the surface, but the main principle here is to ensure you have the right context when executing commands.