Чи є спосіб натиснути і попсувати всі змінні середовища в пакетному сценарії?


10

Чи є спосіб натиснути і попсувати всі змінні середовища в пакетному сценарії? Наприклад, я хотів би зробити щось подібне:

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

Відповіді:


13

Використовуйте setlocal, див. setlocal /?Або ss64.com/nt/setlocal

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

Для збереження поточного стану змінної ви могли б зробити

set >MyVarStatus.txt

і відновити пізніше с

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

це виключає змінні Path.


Ви виключаєте PATH- лише, наприклад, або чомусь. Мене особливо цікавить зміна "push / pop". Чи є щось, що говорить проти резервного копіювання / відновлення PATH?
Вовк

Насправді і те, і приклад, і якщо тим часом важливі зміни були застосовані до шляху, тим часом запобіжні заходи. @wolf
LotPings

Добре, ви не можете бути впевнені у всіх випадках, але якщо вам доведеться додати щось до контуру лише для конкретного сеансу, ви, безумовно, зацікавлені відновити шлях після цього. Вам не доведеться цього робити, якби не було зовнішніх інструментів, які викликали б інші інструменти і очікували, що вони опиняться на шляху.
Вовк

1
Код відкритий для змін, якщо потрібно відновити все середовище, просто замініть findstr на тип.
LotPings

Дякую, я просто хотів бути впевненим, щоб не помітити нічого важливого.
Вовк

1

Трохи запізнюючись на сцену, але тут все одно йде. Нижче представлена ​​реалізація структури даних стека в пакетному сценарії Windows.

Особливості:

  • Ви повинні викликати підпрограму : InitializeStack перед використанням стека.
  • Натисніть на елементи стека, зателефонувавши : Підпрограма Push .
  • Вискочіть елементи зі стека, зателефонувавши у програму : Pop .
  • Змінна $ Count завжди буде містити кількість елементів у стеку.
  • Змінна $ Top завжди буде містити останній елемент, доданий до стеку.
  • Змінна $ Bottom завжди буде містити перший елемент, доданий до стеку.
  • Ви можете скинути вміст стеку, зателефонувавши в підпрограму : DumpStack .
  • Тип елементів, які можна натиснути на стек, - це все, що можна зберігати в змінній. Наприклад, зателефонувати: натиснути "Рядок 1" , зателефонувати: натиснути "% 1" , зателефонувати: натиснути "% MyVariable%" тощо.

Я використовую стек у своїх пакетних файлах для відстеження викликів підпрограми. Кожна підпрограма в моїх пакетних файлах починається з Call: Push% 0 , яка висуває ім'я поточної підпрограми на стек і закінчується Call: Pop .

Деякі можуть вважати це надмірним вбивством для пакетного сценарію, але мені сподобалося його створювати, і я сподіваюся, що хтось знайде це корисним, сподобається .

@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

Отже, для витіснення всіх змінних оточуючих середовищ ви можете викликати: PushAllEnvironmentVariables, щоб відновити всі змінні середовища, ви можете зателефонувати: PopAllEnvironmentVariables


Це виглядає - поглядом - як щось таке, що, можливо, потребувало певних зусиль, щоб розробитись, а може бути корисним комусь. Чи можете ви пояснити, як це дає відповідь на це питання ?
Скотт

Я бачу вашу думку, щоб підштовхнути всі змінні середовища, які ви можете використовувати: For /f "Tokens=* Delims=" %%a In ('Set') Do Call :Push "%%a" Щоб відновити всі змінні середовища, які ви можете використовувати: For /l %%a In (!$Stack[0]!,-1,1) Do (Set !$Stack[%%a]!) я оновив відповідь, щоб включити дві підпрограми, які це реалізують.
Сафван
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.