管道 命令 %errorlevel! 环境变量 优先级 问题 随笔 CMD /V 延迟的环境变量

AHK/AutoHotkey测试:


shell := ComObjCreate("WScript.Shell") ExecThenOutput(command){ global shell exec := shell.Exec(ComSpec " /C " . command) FileAppend, % exec.StdOut.ReadAll() "`n",* } ExecThenOutput("net session 2>&1") ; 发生系统错误 5。拒绝访问。 ExecThenOutput("echo %errorlevel%") ; 0 ExecThenOutput("net session 2>&1 && echo %errorlevel%") ; 发生系统错误 5。拒绝访问。 ExecThenOutput("net session 2>&1 `; echo %errorlevel%") ; 此命令的语法是:.. ExecThenOutput("net session 2>&1 || echo %errorlevel%") ; 发生系统错误 5。拒绝访问。 ; 0 ExecThenOutput("chcp") ; 活动代码页: 936 ExecThenOutput("net session 2>&1 | chcp") ; 活动代码页: 936 ExecThenOutput("net session 2>&1 | echo %errorlevel%") ; 0

更正见后。

使用管道符"|"连接的两命令,后一个命令中的变量(如下的errorlevel)的(运行时)值独立于先于前一个命令,或者说,前一个命令不影响后一个命令中的变量,或者说,变量求值先于(前、后)命令,或者说,变量求值的运行时先于管道命令管道运算先于命令
运算优先级/顺序:变量求值>管道运算>命令。

C:WINDOWSsystem32>net session >nul 2>&1 |  %errorlevel%
'0' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

C:WINDOWSsystem32>net session >nul 2>&1 |  %errorlevel%
'9009' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

C:WINDOWSsystem32>net session >nul 2>&1 | echo %errorlevel%
9009

C:WINDOWSsystem32>net session >nul 2>&1 | echo %errorlevel%
0
C:UsersRobertL>net session >nul 2>&1
C:UsersRobertL>echo %errorlevel%
2

 但以上即便ExecThenOutput("net session 2>&1")ExecThenOutput("echo %errorlevel%"),(echo)仍显示0(不同于命令行下),如同两次执行彼此无关、不在一个环境中。

验证(命令行下,AHK的WScript.Shell不同?)

>set x=1 & echo %x%

>set x=2 & echo %x%
1
>set x=3 & echo %x%
2

尝试: shell当中多个命令放在一起执行的几个方法_huangzx3的博客-CSDN博客

非管理员下:
C:UsersRobertL>net session >nul 2>&1 ; echo %errorlevel%

C:UsersRobertL>net session >nul 2>&1 && echo %errorlevel%

C:UsersRobertL>net session >nul 2>&1 || echo %errorlevel%
2 (实为前一个命令的errorlevel)

管理员下:
C:WINDOWSsystem32>net session >nul 2>&1 ; echo %errorlevel%

C:WINDOWSsystem32>net session >nul 2>&1 || echo %errorlevel%

C:WINDOWSsystem32>net session >nul 2>&1 && echo %errorlevel%
0 (实为前一个命令的errorlevel)

类似的,有:shell命令串联起来执行的几种方法_hoooo1的博客-CSDN博客_shell拼接命令并执行
分号";"连接总是无效(如同没有分号后的内容)(见下)

类似的,有:如何在 Windows CMD 中的一行中运行两个命令? - 协慌网 (routinepanic.com)
尝试使用&,总是有效(如同上面的";“),但实为前一个命令的errorlevel。
尝试^T,无效(如同没有其后的内容)。

尝试:如何通过WScript.Shell连续调用命令行-CSDN论坛 (googleusercontent.com)
StandardInput.WriteLine(..)

参见:关于vba:在WScript.Shell对象中调用Run时无法识别环境变量 | 码农家园 (codenong.com)
推荐,但属于搬运、翻译。
相关/扩展:关于cmd:是否有命令从Windows中的命令提示符刷新环境变量? | 码农家园 (codenong.com)

搜索:命令行 命令 连续 串联 WScript.Shell 环境变量 errorlevel - Google 搜索
WScript.Shell exec errorlevel - Google 搜索

参考:windows - Get errorlevel in bat from vbscript - Stack Overflow
WScript.Quit


参考:windows - Getting the return value from a cmd /c command in VBScript - Stack Overflow

/V:ON 使用 ! 作为分隔符启用延迟的环境变量
扩展。例如,/V:ON 会允许 !var! 在执行时
扩展变量 var。var 语法会在输入时
扩展变量,这与在一个 FOR
循环内不同。

如果延迟环境变量扩展被启用,
惊叹号字符可在执行时间被用来
代替一个环境变量的数值。

Start the cmd instance with delayed expansion enabled (/v) and exit the cmd instance with the errorlevel set by the previous command.

Delayed expansion is needed because the cmd parser replaces all %var% read operations with the value inside the variables during the line/block parse phase. Without delayed expansion (%errorlevel%), the value to be returned by the exit command will be retrived before starting to execute the command. With delayed expansion (!errorlevel!) the value will be retrieved when the exit command is executed, after the commandGoesHere has ended.

测试

echo %x% !x! & set x=2 & echo %x% !x!
1  1
1  2

使用/V选项并搭配!分隔符后的测试,正常:

shell := ComObjCreate("WScript.Shell")
ExecThenOutput(command){
    global shell
    exec := shell.Exec(ComSpec " /V:ON /C " . command)
    FileAppend, % exec.StdOut.ReadAll() "`n",*
}
ExecThenOutput("net session >nul 2>&1 || echo !errorlevel!")
;    when not Administrator Mode 2
;    when  Administrator Mode 0

 参考:scripting - VBScript getting results from Shell - Stack Overflow
exec.Status/ExitCode / exec.StdErr/StdOut
WScript.StdOut.Write / WScript.Echo

原文地址:https://www.cnblogs.com/RobertL/p/14818503.html