Dienstag, 27. November 2007

BATCH_ Subroutines in Windows Batch

Since Windows 2000 you can use subroutines (depending on the understanding and definition of "function" and "procedure", one can also refer to them as "procedures", that can manipulate both local and global variables and don't return any value ("void")).

Basically, a subroutine is a number of commands between a label and a GOTO:EOF statement.
:MY_SUBROUTINE
ECHO Called MY_SUBROUTINE and ending now...
GOTO:EOF

GOTO:EOF is often written without a space, as it is used as a special GOTO command: It jumps to the End of File, thus ending the currently executed script.

That is the reason why a subroutine is not called with GOTO :MY_SUBROUTINE, but with
CALL :MY_SUBROUTINE

This executes the current batch AGAIN in the current context, but jumps immediately to the given label. And that is the reason why ending the script at the end of the subroutine - it just ends the execution started through the CALL command.

A subroutine has its own parameters, you don't have access to the "parent" batch parameters unless they were stored in an environment variable.
CALL :MY_SUBROUTINE "param 1" "param 2"
GOTO:EOF

:MY_SUBROUTINE
ECHO The first parameter is %~1.
ECHO The second parameter is %~2.
GOTO:EOF

You can see that there is another GOTO:EOF after the CALL command. You don't want your first subroutine being executed after your script finished, do you? This is the basic structure of a batch script using subroutines:
@ECHO off
REM Documentation here
REM Version 1.0 of 2007/11/11

... preprocessing, setting variables etc ...
... script body ....

GOTO:EOF
REM ############################
REM SUBROUTINES
:MY_SUBROUTINE
... subroutine body
GOTO:EOF


What about the local context I mentioned at the beginning? That does not differ from standard batch scripts:
:MY_SUBROUTINE
SETLOCAL
... local context here ...
ENDLOCAL
GOTO:EOF


As subroutines do not provide a way of returning any value (and, of course, there is no direct way to store the result of an execution in a variable), here is what I do. By convention, I reserve the global variable %RESULT% for storing the result of the last called subroutine that should return a value. You can think of it like putting a value onto a one-element stack.
:MY_SUBROUTINE
SET RESULT=4711
GOTO:EOF

This won't work if using local context within the subroutine, however due to the cmd.exe-nature there is way to preserve a variable after ending the local context:
:MY_SUBROUTINE
SETLOCAL
SET RESULT=4711
ENDLOCAL & SET RESULT=%RESULT%
GOTO:EOF

A little explanation: As the batch reads a full line, expands all variables, parses the line and then finally executes all contained commands in order, the important line looks like this after expansion:
ENDLOCAL & SET RESULT=4711
See, variable preserved and available in global context. Sometimes you want to preserve more than one variable, so you add additional SET statements. But be careful and do not insert a space before the ampersand - that space will contained in your variable!
ENDLOCAL & SET A=%A%& SET B=%B%& SET C=%C%

A little advise at the end: document your subroutines, otherwise you won't know what parameters it takes, what global variables it manipulates or requires or what value it "returns". I use double colons for subroutine documentation.
:: Shortens a string to the given number of characters.
:: PARAMS
:: 1 string to shorten
:: 2 number of characters
:: RESULT String shortened string
:SHSTR
SETLOCAL ENABLEDELAYEDEXPANSION
SET TEMP=%~1
ENDLOCAL & SET RESULT=!TEMP:~0,%~2!
GOTO:EOF

See also this article about handling parameters and variables containing special characters.

Reflog

Informationstechnische Howtos, Hinweise und Merkwürdiges

Batchlib v1.0 2008-03-29

Aktuelle Beiträge

HOWTO_ O2 DSL Surf &...
Der O2 DSL Surf & Phone-Router ist für die alleinige...
cypressor - 12. Feb, 19:57
Uptweak Windows XP Home...
There are a lot of annoying limitations in Windows...
cypressor - 9. Okt, 19:30
BATCHLIB_ Batchlib package...
Download Batchlib package v1.0 (5 KB zip file) What...
cypressor - 29. Mär, 19:10
BATCHLIB_ Batchlib library...
The batchlib library string.cmd is part of the batchlib...
cypressor - 29. Mär, 18:10

Homepage Ticker

Links

Status

Online seit 6816 Tagen
Zuletzt aktualisiert: 28. Jun, 11:32
RSS XML 1.0 Button-Get-Firefox

batch
batchlib
howto
tech
video
Profil
Abmelden
Weblog abonnieren