如果脚本在调用EXIT 1
时不在关闭终端的情况下退出子程序。我使用this if
再次调用脚本。
这个工作正常,直到我现在发现一个带引号的竖线作为参数"!"
的问题。我收到一条错误,指出该命令拼写错误。
以下是脚本失败的部分:
@ECHO OFF
SETLOCAL DISABLEDELAYEDEXPANSION
IF "%selfWrapped%"=="" (
REM this is necessary so that we can use "exit" to terminate the batch file,
REM and all subroutines, but not the original cmd.exe
SET selfWrapped=true
%ComSpec% /s /c ""%~0" %*"
GOTO :EOF
)
echo %*
ENDLOCAL
EXIT /B 0
呼叫:
test.cmd "hello world" "|"
预期产出:
"hello world" "|"
我在%*
中检查了IF
的值,但是使用竖线以及任何其他引用的字符串似乎完全合法。
因此...
答案 0 :(得分:3)
我不同意链接中的一些描述。
请参阅exit /?
准确的帮助说明。
exit
退出翻译。exit 1
使用exitcode 1退出解释器。exit /b
具有与退出的goto :eof
类似的行为
脚本或被叫标签。 Errorlevel 未重置,因此允许
errorlevel 从上一个命令可以访问之后
退出脚本或被叫标签。exit /b 1
使用 errorlevel 1 退出脚本或被叫标签。如果您在CMD提示符处奇怪地使用exit /b
,它将退出解释器。
主要代码:
@ECHO OFF
SETLOCAL DISABLEDELAYEDEXPANSION
SET args=%*
SET "self=%~f0"
IF "%selfWrapped%"=="" (
@REM this is necessary so that we can use "exit" to terminate the batch file,
@REM and all subroutines, but not the original cmd.exe
SET "selfWrapped=true"
SETLOCAL ENABLEDELAYEDEXPANSION
ECHO !ComSpec! /s /c ""!self!" !args!"
"!ComSpec!" /s /c ""!self!" !args!"
GOTO :EOF
)
ECHO(%*
EXIT /B 0
使用GOTO :EOF
和EXIT /B 0
都会退出脚本。
脚本退出时隐含ENDLOCAL
。
显式使用ENDLOCAL
是为了结束时间
当前本地范围并继续脚本。一如既往地存在
所有时间都是明确的选择。
将%*
设置为args
会使双引号保持配对。
引用即set "args=%*"
有时会引起问题
虽然不使用引号允许代码注入,即
参数"arg1" ^& del *.*
。如果del *.*
没有进展
要在set
行执行,那么它可能会发生
在ComSpec
行。对于这个例子,我选择不引用。
所以,这是一个选择。
您在脚本开始时使用禁用扩展。那
保存好的!
参数。在你执行之前
ComSpec
但是,启用延迟展开并使用!args!
现在不受翻译的保护现在没有看到|
或任何其他可能引发错误的特殊字符。
您的脚本在|
参数公开时失败。
C:\Windows\system32\cmd.exe /s /c ""test.cmd" " | ""
上面回应了对ComSpec
行的评价
设置@ECHO ON
。注意引号的配对
即""
," "
和""
。注意插入的额外间距
解释器不考虑的|
字符周围
它作为引用字符串的一部分。
与回显评估的更新代码更改相比......:
"!ComSpec!" /s /c ""!self!" !args!"
引号之间的字符串保持不变。没有额外的间距 插入字符串。回应的评估看起来很好 执行得很好。
<强> 声明: 强>
表达CMD的运作就像走紧绳索一样。 就在你认为自己知道的时候,脱掉绳子。
答案 1 :(得分:2)
我根本没有看到将参数附加到%ComSpec% /s /c ""%~0" %*"
的必要性。
由于您已经使用变量(selfWrapped
)来检测,如果需要包装调用,您还可以将参数放入变量中。
set args=%*
然后您可以在您的子实例中使用!args!
。
@ECHO OFF
setlocal DisableDelayedExpansion
IF "%selfWrapped%"=="" (
@REM this is necessary so that we can use "exit" to terminate the batch file,
@REM and all subroutines, but not the original cmd.exe
SET "selfWrapped=true"
SET ^"args=%*"
"%ComSpec%" /s /c ""%~f0""
GOTO :EOF
)
:Main
setlocal EnableDelayedExpansion
ECHO(!args!
EXIT /B 0
现在唯一的问题是set args=%*
如果您无法控制内容,则无法以简单安全的方式访问%*
。
想想这批次调用
myBatch.bat&#34; abc |&#34;
myBatch.bat abc ^ |
myBatch.bat abc ^ | - &#34; |&#34;
但你可以使用How to receive even the strangest command line parameters?
或Get arguments without temporary file
顺便说一下。您可以免除您的子进程,也可以退出功能
看Exit batch script from inside a function
答案 2 :(得分:1)
对上述答案进行一次修正。
是的,脚本末尾隐含ENDLOCAL
,但有一个问题。
我发现使用嵌套脚本时,如果您在ENDLOCAL
之前没有EXIT /B 1
,则不会在下一级获得1
的返回码出脚本。
如果您只有EXIT /B 0
,那么这无关紧要,因为默认返回代码为0
。