1

Я пытаюсь вызвать другой экземпляр CMD и передать ему данные из родительского экземпляра.

Мне известен общий путь использования переменных, но в этом случае это было бы неосуществимо, поскольку endlocal и bridging были бы слишком большими неудобствами (пришлось бы передавать десятки переменных). Я также знаю, что мог бы использовать временные файлы для переноса всех данных, которые я хочу легко, но это оставило бы нежелательные следы. РЕДАКТИРОВАТЬ: setx также может быть использован довольно успешно.

Я специально искал что-то вроде обычного использования аргументов, например:

test.bat -setvar"variable"="value" -setvar...

Я ранее нашел один способ с его ограничениями

Обнаружил в другом потоке, что могу добавить команду в конец запуска cmd

start cmd /c call "test.bat" ^& PAUSE

Конечно, мы можем изменить это

start cmd /c call PAUSE ^& TIMEOUT 5 ^& PAUSE ^& test.bat

Команды не могут иметь "" и, я подозреваю, никаких специальных символов. это представляет проблему при попытке портировать сложные переменные.

Кстати, о специальных персонажах:

start cmd /c call (PAUSE) ^& (TIMEOUT 5) ^& (REM !"#¤%&/=?`´^*"-.,_:;\*~¨) ^& test.bat

Это не будет работать вообще. Я мог бы избежать интерпретации, но в случае некоторых переменных у меня не было бы роскоши знать достаточно значений, чтобы можно было обработать их во все, что я мог бы обработать. - На самом деле, кажется, что скобки не допускаются.

Одна из главных вещей, которые мне нужно сделать, это передать имена томов, что легко достижимо, но этого недостаточно.

start cmd /c call echo \\?\Volume{6537febd-01bc-11d6-adb5-806e6f6e6963}\ ^& TIMEOUT 5 ^& PAUSE ^& test.bat

Это уже может быть рассмотрено в другом месте, и если так, то проблема в том, что я не могу найти правильные ключевые слова или параллели с соответствующими темами.

2 ответа2

2

Дочерний экземпляр cmd наследует все переменные окружения от родительской. Доказательство: давайте создадим два пакетных скрипта:

Test1.bat

@setlocal
@set _batch
@set "_batchParentName=%~nx0"
@set "_batchParentPath=%~dp0"
@set "_batchParentSpec=< LSS > GTR & amper | pipe"
start "%~n0" cmd /C call "test.bat" "%_batchParentSpec%" %* ^& pause
@set _batch

Test.bat

@setlocal
@set _batch
@echo %~n0: %%* = %*

Вывод родительского экземпляра cmd :

d:\bat>test1.bat first "1<2" third
Environment variable _batch not defined

d:\bat>start "test1" cmd /C call "test.bat" "< LSS > GTR & amper | pipe" first "1<2" third
 & pause
_batchParentName=test1.bat
_batchParentPath=D:\bat\
_batchParentSpec=< LSS > GTR & amper | pipe

d:\bat>

Вывод дочернего экземпляра cmd из test.bat:

_batchParentName=test1.bat
_batchParentPath=D:\bat\
_batchParentSpec=< LSS > GTR & amper | pipe
test: %* = "< LSS > GTR & amper | pipe" first "1<2" third
Press any key to continue . . .

Обратите внимание на синтаксис команды start справа с "title":

START "title" [/D path] [options] "command" [parameters]

Всегда включайте TITLE, это может быть простая строка типа "Мой скрипт" или просто пара пустых кавычек »». Согласно документации Microsoft, заголовок является необязательным, но в зависимости от других выбранных параметров могут возникнуть проблемы, если он не указан.

Убедитесь, что команда start не содержит опцию /I (из start /?):

 /I      The new environment will be the original environment passed
         to the cmd.exe and not the current environment.

Чтобы исключить еще одну возможность изменений дочерней среды, включите ключ /D в cmd следующим образом:

start "test1" cmd /D /C call "test.bat"

Согласно cmd /?:

/D      Disable execution of AutoRun commands from registry
1

Вы можете использовать setx для установки переменной окружения, которая является глобальной для ваших окон.

Чтобы использовать setx просто напишите это: setx "name" "variable" где name - это простое имя, а variable - это переменная, которую вы хотите установить.

Смотрите setx /? для всех опций и параметров, если вы хотите пойти немного глубже в опциях.

Обратите внимание, что setx будет хранить переменные непосредственно в кусте текущего пользователя реестра. Это означает, что вам не нужны никакие административные привилегии, но это также означает, что переменные не доступны напрямую в текущем сеансе cmd. Используйте обычный set если вы просто хотите хранить переменные локально.

Вы также можете сохранить локальную переменную в глобальную, как показано в следующем примере:

@echo off
:: store "test" in variable "a"
set a=test

:: make this variable global
setx a %a%

Как видно из приведенного выше примера, %a% ссылается на переменную в локальной области видимости, а setx делает ее общедоступной

Чтобы сбросить глобальную переменную, вызовите эту команду: setx "name" "" например: setx a ""

Также полезно понимать: вы не можете изменить один экземпляр cmd, используя setx в другом. Как только вы запускаете окно cmd, только set может изменять свои переменные внутри, а setx может хранить их снаружи. (при выходе, как вы будете)

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .