Is there a way to push and pop all environment variables in a batch script?

Solution 1:

Use setlocal, see setlocal /? or ss64.com/nt/setlocal

Setlocal
call "%VS140COMNTOOLS%\vsvars32.bat"
(do some stuff...)
Endlocal
Setlocal
call "%VS90COMNTOOLS%\vsvars32.bat"
(do some other stuff...)
Endlocal

To save the current variable state you could do

set >MyVarStatus.txt

and restore later on with

@Echo off
For /f "tokens=1* delims==" %%A in (
  'findstr /V "^Path" MYVarStatus.txt '
) Do Set %%A=%%B

this would exclude the Path variables.

Solution 2:

A bit late to the scene but here goes anyways. Below is an implementation of a stack data structure in Windows batch scripting.

Features:

  • You must call the :InitializeStack subroutine before using the stack.
  • Push items on the stack by calling the :Push subroutine.
  • Pop items off the stack by calling the :Pop subroutine.
  • The variable $Count will always contain the count of items in the stack.
  • The variable $Top will always contain the most recent item added to the stack.
  • The variable $Bottom will always contain the first item added to the stack.
  • You can dump the content of the stack by calling the :DumpStack subroutine.
  • The type of items that you can push on the stack is anything that can be stored in a variable. For example, Call :Push "String 1", Call :Push "%1", Call :Push "%MyVariable%", etc.

I use the stack in my batch files to keep track of subroutine calls. Every subroutine in my batch files starts with Call :Push %0, which pushes the current subroutine's name onto the stack and ends with Call :Pop.

Some may find it an over-kill for batch scripting but I enjoyed creating it and I hope someone will find this useful, enjoy.

@Echo Off
Cls
SetLocal
SetLocal EnableExtensions
SetLocal EnableDelayedExpansion

Call :InitializeStack

Call :Push "String 1"
Call :Push "String 2"
Call :Push "String 3"
Call :Pop

Echo Total items in stack = !$Count!
Echo Top of stack         = !$Top!
Echo Bottom of stack      = !$Bottom!
Call :DumpStack

Goto End

:InitializeStack
:------------------------------------------------------------
Set "$Stack[0]=0"
Set "$Count=!$Stack[0]!"
Set "$Top="
Set "$Bottom="
Exit /b

:DumpStack
:------------------------------------------------------------
If !$Stack[0]! EQU 0 (
  Echo Stack is empty.
) Else (
  Echo.
  Echo Stack Dump
  Echo ----------
  For /l %%a In (!$Stack[0]!,-1,1) Do (Echo !$Stack[%%a]!)
)
Exit /b

:Push <String>
:------------------------------------------------------------
Set /a "$Stack[0]+=1"
Set "$Count=!$Stack[0]!"
Set "$Top=%~1"
Set "$Bottom=!$Stack[1]!"
Set "$Stack[!$Stack[0]!]=!$Top!"
Exit /b

:Pop
:------------------------------------------------------------
If !$Stack[0]! EQU 0 (
  Echo "Stack is empty."
) Else (
  Set "$Stack[!$Stack[0]!]="
  Set /a "$Stack[0]-=1"
  Set "$Count=!$Stack[0]!"
  If !$Stack[0]! GTR 0 (
    For %%a In (!$Stack[0]!) Do Set "$Top=!$Stack[%%a]!"
    Set "$Bottom=!$Stack[1]!"
  ) Else (
    Set "$Top="
    Set "$Bottom="
  )
)Exit /b

:PushAllEnvironmentVariables
:------------------------------------------------------------
For /f "Tokens=* Delims=" %%a In ('Set') Do Call :Push "%%a"
Exit /b

:PopAllEnvironmentVariables
:------------------------------------------------------------
For /l %%a In (!$Stack[0]!,-1,1) Do (Set !$Stack[%%a]!)
Exit /b

:End

So, to push all environment variables you can call :PushAllEnvironmentVariables, to restore all environment variables, you can call :PopAllEnvironmentVariables