2016-09-21 116 views
5

为什么不低于批处理文件保持变量时的CMD.exe终止批处理文件不守变量

@echo off 
cmd /c "set var=hi" 
if defined var (echo var is defined ("var=%var%")) else (echo var isn't defined) 
pause 
exit 

有没有办法使用CMD/C,同时保持变量?为什么CMD/c不保存变量?

+4

为什么你使用'cmd/c“set var = hi”'?这将在子进程中创建变量,并且变量将随着它而死。 – npocmaka

+1

我很欣赏你使用的是MCVE(严重的是,这个标签超级难得),但为什么在这个世界上你会设置这样的变量? – SomethingDark

+0

@SomethingDark,这只是一个例子。在实际使用中,我会在批处理文件中调用cmd/c“%〜0”',然后当批处理文件退出时,它将返回到主脚本。这是我能想到的'保持'批处理文件终止其自我的唯一方法。另外,如果CMD/c保存了变量,那么它将允许脚本的其余部分访问它设置的变量。长时间解释soz –

回答

3

CMD/C开始一个新的子进程,具有这样的变量存储在内存中它自己的环境空间。当这个过程终止时,相关的环境空间就会丢失,所以你当然会失去在那里定义的任何变量的定义。

用于子过程直接访问或操纵父进程的变量这是不可能的。

如果您要执行一个简单的命令,并拥有控制权的任何输出,那么你可以写的定义,标准输出,让FOR/F捕获输出,这样就可以在你的父进程设置的值。但是你需要延迟扩展。

注 - 这个例子是很空洞,但它应该得到点跨越

for /f "delims=" %%A in ('cmd /v:on /c "set var=hi&echo "var=!var!""') do set %%A 

但事情可能会变得远为复杂,确定什么是引用,需要转义什么,...如果你创建一个批处理脚本,做的工作,并用FOR/F执行它

生命可以被简化。

test.bat的

@echo off 
set var1=hi 
set var2=Ain't this fun 
set var3=bye 
setlocal enableDelayedExpansion 
for %%V in (var1 var2 var3) do echo "%%V=!%%V!" 

main.bat

@echo off 
for /f "delims=" %%A in ('cmd /c test.bat') do set %%A 

其实,FOR/F采用隐式CMD/C,你不再需要启用延迟扩展命令,这样你就可以抛弃明确CMD/C

@echo off 
for /f "delims=" %%A in ('test.bat') do set %%A 

如果您不能控制输出,那么您必须将这些值写入主脚本可以加载的临时文件中。您可能会试图编写一个临时批处理脚本来定义变量,但随后您将冒着必须转义某些字符的风险,具体取决于变量的内容。最安全的选择是使用延迟扩展写出来的变量名和值,并让父进程使用FOR/F向他们加载。

test2.bat

@echo off 
set var1=hi 
set var2=Ain't this fun 
set var3=bye 
echo Here is some output that must be preserved, unrelated to variables 
setlocal enableDelayedExpansion 
(for %%V in (var1 var2 var3) do echo "%%V=!%%V!") >"%temp%\vars.temp" 

为主。蝙蝠

@echo off 
setlocal disableDelayedExpansion 
cmd /c test2.bat 
call "%temp%\vars.bat" 
for /f "usebackq delims=" %%V in ("%temp%\vars.temp") do set "%%V" 
del "%temp%\vars.temp" 

注意,延迟扩展必须在主要的过程,当你加载变量被禁用,否则你将失去任何VALU字符! es当​​3210扩展时。

但要健壮,你应该做的事情,以确保每个实例使用唯一的临时文件名,以便同时运行不揍海誓山盟。

+1

在实际使用中,我会在批处理文件中执行调用'cmd/c“%〜0”',然后当批处理文件退出时,它将返回到主脚本。这是我能想到的'保持'批处理文件终止其自我的唯一方法。另外,如果CMD/c保存了变量,那么它将允许脚本的其余部分访问它设置的变量。你能想到任何其他的解决方案,可以让批处理文件自己调用它,同时保持它的环境空间吗? –

+0

@BurnieRiley - 只需在脚本的开头添加一个'setlocal',脚本终止后,所有设置在脚本内部的变量都将被取消设置。 – SomethingDark

+0

@BurnieRiley - 见我编辑的答案。 – dbenham