DOS - Persistent Variables

Want to remember the state of your DOS batch over different sessions?

Want to make you DOS batch available in the network but store user preferences local?

Persist variables is what you need.

 

Ideally you somehow mark your variables to be persistent and have one function to store all persistent variables and one function to restore persistent value back into the variables.  Learn here how to do this.

 

1      Example Batch to Start With. 1

2      Mark Variables to be Persistent. 2

3      getPersistentVars – Function. 2

4      savePersistentVars – Function. 3

5      restorePersistentVars – Function. 3

6      Example – Persistent Variables. 3

 

 

1        Example Batch to Start With

Description

Copy the following code into an empty batch file (e.g.: ”DosTips.bat”).  Get familiar with it by executing it and changing some of the variables when prompted.  Close the application using the “q” option and then run it again.  As you will see all variable changes from the previous run are lost.

Code

@echo off

rem.--- Prepare the Command Processor ---

SETLOCAL ENABLEEXTENSIONS

SETLOCAL ENABLEDELAYEDEXPANSION

 

rem.--initialize the variables

set color=1e

set lines=20

set title=Hello World

 

:LOOP

 

rem.--apply the variable settings

color %color%

title %title%

MODE CON: LINES=%lines% COLS=80

 

rem.--show current settings

echo.Currently the variables are:

echo.

echo.  color=%color%

echo.  lines=%lines%

echo.  title=%title%

echo.

echo.

 

rem.--let the change the variables

echo.Assign new values, for example enter:

echo.

echo.  color=2e

echo.  lines=40

echo.  title=HI THERE

echo.

set cmd=

set /p cmd=Or enter q to quit:

if /i "%cmd%"=="q" (

    GOTO:EOF

)

 

rem.--execute the SET command and loop back

SET %cmd%

GOTO:LOOP

 

This batch program uses three variables color, lines, and title.  The user can change the variables.  However after closing the application with ‘q’ all settings are gone.  Our goal is to have all three variables persistent so that when running the batch next time the previews setting show up.

2        Mark Variables to be Persistent

Description

The challenge is to mark a variable as persistent but still keep the code looking good and maintainable.  Changing the SET command to a function call where the variable gets initialized the first time meets the requirement:

Code

call:setPersist color=1e

call:setPersist lines=20

call:setPersist title=Hello World

 

The setPersist function will just do what the set function did, assigning a value to the variable.

Code

:setPersist -- to be called to initialize persistent variables

:           -- %*: arguments for the SET command

set %*

GOTO:EOF

 

Of course just replacing the SET command with a call to setPersis doesn’t make the variable persistent, but we can write another function now that parses the batch file for all lines containing the call:setPersist  command and automatically persist the corresponding variables.

3        getPersistentVars – Function

Description

The getPersistentVars function parses its owning batch file for lines calling the setParsist function and collects the associated variables in a comma separated list.  The comma speared list of strings can easy be parsed later using the FOR function.

Code

:getPersistentVars -- returns a comma separated list of persistent variables

:                  -- %~1: reference to return variable

SETLOCAL

set retlist=

set parse=findstr /i /c:"call:setPersist" "%~f0%"^|find /v "ButNotThisLine"

for /f "tokens=2 delims== " %%a in ('"%parse%"') do (set retlist=!retlist!%%a,)

( ENDLOCAL & REM RETURN VALUES

    IF "%~1" NEQ "" SET %~1=%retlist%

)

GOTO:EOF

How it works

The findstr command applied to "%~f0%" (the batch file itself ) filters all lines having the “call:setPersist” command in it, which is what we want.  In addition it finds the line that searches for the “call:setPersist“ string within the getPersistentVars function itself, which we don’t want.  So we need to pipe the findstr output into another find command that filters the unwanted output.  The resulting parser code will be stored into the parse variable and is being used in the FOR command of the next line.

The FOR command splits each line found by the parse command using “ ” (space) and “=” (assignment operator) as delimiters.  This way the first token found will always be the string “call:setPersist” and the second token will always be the variable name that we are looking for.

The variable name will then be added to the return list called retlist adding a trailing comma in order to separate the variable names from each other.

4        savePersistentVars – Function

Description

The savePersistentVars function creates an executable batch file having a SET command for each variable to be persisted.  The values can easily be restored by executing this batch file.

Code

:savePersistentVars -- Save values of persistent variables into a file

:                   -- %~1: batch file name to save to

SETLOCAL

echo.>"%~1"

call :getPersistentVars persvars

for %%a in (%persvars%) do (echo.SET %%a=!%%a!>>"%~1")

GOTO:EOF

How it works

The SETLOCAL call ensures that changes to the persvars variable is invisible outside the function.  A corresponding ENDLOCAL is implicitly being executed by the GOTO:EOF command at the end of the function.

The echo.>"%~1" command creates an empty new file whether or not one already exist.

The call to getPersistentVars returns the comma separated list of persistent variables into the persvars variable.

The persvars variable is then being parsed by the FOR command which adds a

SET <VAR>=<CURRENTVALUE> entry for each persistent variable to the new created file.

5        restorePersistentVars – Function

Description

The restorePersistentVars function shall simply execute the batch file that stores the commands to restore the persistent variables.

 

:restorePersistentVars –- Restore the values of the persistent variables

:                      -- %~1: batch file name to restore from

if exist "%FilePersist%" call "%FilePersist%"

GOTO:EOF

6        Example – Persistent Variables

Description

Some modifications have been made to the previous example in order to make the variables for the color, the number of lines, and the window title persistent.  The relevant modification are shown in bold below.

Copy the new code into an empty batch file (e.g.: ”DosTips.bat”).  Get familiar with it by executing it and changing some of the variables when prompted.  Close the application using the “q” option and reopen it.  As you will see the variables show the values as set in the previous run.

Code

@echo off

rem.--- Prepare the Command Processor ---

SETLOCAL ENABLEEXTENSIONS

SETLOCAL ENABLEDELAYEDEXPANSION

 

rem.--define the filename where persistent variables get storred

rem.  just add a + to the name of THIS file, i.e. "DosTips.bat" - "DosTips+.bat"

set FilePersist=%~dpn0+%~x0

 

rem.--initialize the variables

call:setPersist color=1e

call:setPersist lines=20

call:setPersist title=Hello World

 

rem.--restore the persistent variables

call:restorePersistentVars "%FilePersist%"

 

:LOOP

 

rem.--apply the variable settings

color %color%

title %title%

MODE CON: LINES=%lines% COLS=80

 

rem.--show current settings

echo.Currently the variables are:

echo.

echo.  color=%color%

echo.  lines=%lines%

echo.  title=%title%

echo.

echo.

 

rem.--let the change the variables

echo.Assign new values, for example enter:

echo.

echo.  color=2e

echo.  lines=40

echo.  title=HI THERE

echo.

set cmd=

set /p cmd=Or enter q to quit:

if /i "%cmd%"=="q" (

    call:savePersistentVars "%FilePersist%"

    GOTO:EOF

)

 

rem.--execute the SET command and loop back

SET %cmd%

GOTO:LOOP

 

 

:-----------------------------------------------------

:-- functions to be added below here

:-----------------------------------------------------

 

 

:setPersist -- to be called to initialize persistent variables

:           -- %*: set command arguments

set %*

GOTO:EOF

 

 

:getPersistentVars -- returns a comma separated list of persistent variables

:                  -- %~1: reference to return variable

SETLOCAL

set retlist=

set parse=findstr /i /c:"call:setPersist" "%~f0%"^|find /v "ButNotThisLine"

for /f "tokens=2 delims== " %%a in ('"%parse%"') do (set retlist=!retlist!%%a,)

( ENDLOCAL & REM RETURN VALUES

    IF "%~1" NEQ "" SET %~1=%retlist%

)

GOTO:EOF

 

 

:savePersistentVars -- Save values of persistent variables into a file

:                   -- %~1: file name

SETLOCAL

echo.>"%~1"

call :getPersistentVars persvars

for %%a in (%persvars%) do (echo.SET %%a=!%%a!>>"%~1")

GOTO:EOF

 

 

:restorePersistentVars –- Restore the values of the persistent variables

:                      -- %~1: batch file name to restore from

if exist "%FilePersist%" call "%FilePersist%"

GOTO:EOF

 

After closing the batch application using the “q” option a new file is being created in the same directory as the batch application itself.  The new created batch file list all persistent variables, i.e.:

Output

SET color=2e

SET lines=20

SET title=Hi There

Note

From here on it’s easy to add more persistent variables.   Simply add another variable to the “initialize the variables” section of the batch file, e.g.:

Code

call:setPersist myvar=myvalue