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

10

1

Is there a way to push and pop all environment variables in a batch script? For example I would like to do something like this:

pushEnvironmentVariables
call "%VS140COMNTOOLS%\vsvars32.bat"
(do some stuff...)
popEnvironmentVariables
pushEnvironmentVariables
call "%VS90COMNTOOLS%\vsvars32.bat"
(do some other stuff...)
popEnvironmentVariables

שלומי שטיין

Posted 2016-12-26T13:41:28.573

Reputation: 103

Answers

13

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.

LotPings

Posted 2016-12-26T13:41:28.573

Reputation: 6 150

You exclude PATH -- just for example or for some reason. I'm especially interested in push/pop the path variable. Is there anything that speaks against backup/restore PATH? – Wolf – 2017-06-14T12:17:26.077

In fact both, an example and in case important changes were applied to the path in the meantime a precaution. @wolf – LotPings – 2017-06-14T12:21:08.810

Well, you cannot be sure in all cases, but if you have to add something to the path for a specific session only, you are definitely interested in restoring the path afterwards. You'd not have to do this if there weren't external tools that call other tools and expecting them to be in the path. – Wolf – 2017-06-14T12:24:07.213

1The code is open to changes, if one wants to restore the whole environment simply replace findstr with type. – LotPings – 2017-06-14T12:29:13.343

Thanks, I just wanted to be sure not to overlook anything important. – Wolf – 2017-06-14T12:52:01.610

1

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

Safwan

Posted 2016-12-26T13:41:28.573

Reputation: 11

This looks —at a glance— to be something that maybe took some effort to develop, and maybe could be useful to somebody.  Can you explain how this *provides an answer to this question?* – Scott – 2019-08-07T06:05:38.573

I see your point, to push all environment variables you can use:

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

To restore all environment variables you can use:

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

I have updated the answer to include 2 subroutines that implements this. – Safwan – 2019-08-08T08:39:06.240