Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Variables 批处理文件不保留变量_Variables_Batch File_Cmd - Fatal编程技术网

Variables 批处理文件不保留变量

Variables 批处理文件不保留变量,variables,batch-file,cmd,Variables,Batch File,Cmd,当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不保留变量?CMD/c启动一个新的子进程,它有自己的环境空间,变量存储在内存中。当该进程终止时,关联的环境空间将丢失,因此您当然会丢失在

当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不保留变量?

CMD/c启动一个新的子进程,它有自己的环境空间,变量存储在内存中。当该进程终止时,关联的环境空间将丢失,因此您当然会丢失在此定义的任何变量的定义

子进程不可能直接访问或操作父进程的变量

如果您正在执行一个简单的命令并控制任何输出,那么您可以将定义写入stdout,并让FOR/F捕获输出,以便您可以在父进程中设置值。但您需要延迟扩展

注意——这个例子很空洞,但它应该能让人明白这一点

但事情可能会变得复杂,因为要确定引用的内容、需要转义的内容

如果您创建一个执行该工作的批处理脚本并使用FOR/F执行它,则可以简化工作

测试.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!"
@echo off
for /f "delims=" %%A in ('cmd /c test.bat') do set %%A
@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"
main.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!"
@echo off
for /f "delims=" %%A in ('cmd /c test.bat') do set %%A
@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"
实际上,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
setlocal enableDelayedExpansion
for %%V in (var1 var2 var3) do echo "%%V=!%%V!"
@echo off
for /f "delims=" %%A in ('cmd /c test.bat') do set %%A
@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"
main.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!"
@echo off
for /f "delims=" %%A in ('cmd /c test.bat') do set %%A
@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"
请注意,加载变量时,必须在主进程中禁用延迟扩展,否则将丢失所有
%%V
时值中的code>字符


但是为了保持健壮性,您应该做一些事情来确保每个实例化使用一个唯一的临时文件名,以便同时运行不会相互碰撞。

为什么要使用
cmd/c“set var=hi”
?这将在子进程中创建变量,变量将随之消亡。我很感激您使用MCVE(说真的,这在这个标签上非常罕见),但您为什么要这样设置变量?@SomethingDark,这只是一个例子。在实际使用中,我将在批处理文件中执行
callcmd/c“%~0”
,然后当批处理文件退出时,它将返回到主脚本。这是我能想到的唯一一种防止批处理文件自行终止的方法。此外,如果CMD/c保留了变量,那么它将允许脚本的其余部分访问它设置的变量。很长的解释,因为批处理文件本身就是
%0
,为什么不调用“%~0”
?@somethingsdark如果批处理文件崩溃,例如,将|&放入批处理文件,那么它只会终止父窗口,即使已经调用了它。如果使用
调用cmd/c“%~0”
,它只会终止子cmd进程,而不是父进程。它有点像沙盒,如果你知道我在实际使用中的意思,我会在批处理文件中执行call
cmd/c“%~0”
,然后当批处理文件退出时,它会返回到主脚本。这是我能想到的唯一一种防止批处理文件自行终止的方法。此外,如果CMD/c保留了变量,那么它将允许脚本的其余部分访问它设置的变量。你能想出任何其他解决方案,允许批处理文件在保持其环境空间的同时调用其自身吗?@BurnieRiley-只需在脚本的开头添加一个
setlocal
,脚本中设置的所有变量都将在脚本终止后取消设置。