Occasionally, one gets in touch with kind of ‘foreign’ technologies and needs to get stuff working anyways.
Recently, I had to do some various hacking with and around .bat files. Bat files are a kind of script files for Microsoft Windows.
Calling external commands
Imagine need to call some other command, let’s say git diff. So from a cmd thing, you would write
1 |
git diff |
similar to writing shell scripts on unixes. But there is a catch. If the thing you want to call is another bat-script, just calling it ensures it ‘replaces’ the current script and never returns. So you need
1 |
call git diff |
if the command you want to run is a bat file and you want to return to your script.
Calling an external helper next to your script
If you for some reason needs to call some external helper placed next to your script, there is a helpful thing to do that as well. Imagine your helper is called helper.bat
1 |
call %~dp0helper.bat |
is the very self-explanatory way of doing that.
Stopping execution of your script
If you somehow encounter some condition in your script that requires you to stop your script, there is a command ‘exit’ handy. It even takes a argument for what error code there is.
1 |
exit 2 |
stops your script with return code 2. But it also have the nice added feature that if you do it in a script you run by hand in a terminal, it also exits the terminal.
Luckily there is also a fix for that:
1 |
exit /b 2 |
and it doesn’t exit your interactive terminal, and it sets the %ERRORLEVEL% variable to the exit code.
Fortunately, the fun doesn’t stop here.
If the script is run non-interactively, exit /b doesn’t set the exit code for for example perl’s system() call. You need to use exit without /b for that. So now you need two scripts. one for “interactive” use that calls exit /b and a similar one using exit for use by other apps/scripts.
Or, we can combine some of our knowledge and add a extra layer of indirection.
- write your script for interactive use (with exit /b) and let’s call it script.bat
- create a simple wrapper script
12call %~dp0script.batexit %ERRORLEVEL%
- call the wrapper for non-interactive use
and then success.
Oh. and on a unrelated note. Windows can’t schedule tasks for users that aren’t logged in and don’t have a password set. The response “Access Denied” is the only clue given.
Yeap, not to mention the inherent limitations of cmd.exe compared to something like bash…
By the way, you should probably use .cmd files instead of .bat. The differences are subtle, but they exist, kind of like the differences between #!/bin/sh and #!/bin/bash:
http://stackoverflow.com/questions/148968/windows-batch-files-bat-vs-cmd
Some possibly useful batch file tricks from The Old New Thing:
http://blogs.msdn.com/b/oldnewthing/archive/2005/09/09/462906.aspx
http://blogs.msdn.com/b/oldnewthing/archive/2012/07/31/10334556.aspx
http://blogs.msdn.com/b/oldnewthing/archive/2012/08/02/10334559.aspx
http://blogs.msdn.com/b/oldnewthing/archive/2012/08/03/10334560.aspx