如何在 cmd /c 中设置 %ERRORLEVEL%?

How to set %ERRORLEVEL% in cmd /c?

我希望能够将 %ERRORLEVEL% 环境变量(也称为“系统变量”)设置为 任意值 在命令提示符脚本的开头(即 cmd /c)运行ning 在 PowerShell 中。每当人们想要设置 %ERRORLEVEL% (1) 时,他们会执行以下操作:

cmd /c "exit /b 3"
cmd /c "echo %ERRORLEVEL%" 

然而,虽然在正常的命令提示符中上面是 运行 时 %ERRORLEVEL% 设置为 3,但是如果这些确切的行在 PowerShell 中执行,退出代码环境变量设置为3并保持0。此外,您不能执行以下操作:

cmd /v:on /c "exit /b 3 & echo !ERRORLEVEL!"

exit命令完全脱离命令执行(即cmd /c),&后没有其他命令是运行。

因此,我尝试在 PowerShell 中执行以下命令:

cmd /v:on /c "SET %ERRORLEVEL% = 4 & echo !ERRORLEVEL!"

预期的输出是 4,但这总是输出 0。我不明白为什么我无法 SET %ERRORLEVEL% 环境变量。我使用了延迟命令执行 (),但这里似乎没有多少摆弄。

有人知道为什么命令 SET %ERRORLEVEL% = 4 不起作用吗?

如果你能够SET环境变量,那么如何将%ERRORLEVEL%设置为由&符号分隔的命令字符串中的任意值(&) 像上面那样?

如果您想将 最终 退出代码存储在 cmd.exe 变量中,以便 以后 使用 exit, 尝试设置ERRORLEVEL;相反,使用自定义变量名称;例如,ec(对于 exit c颂歌):

# Execute in PowerShell
PS> cmd /v /c 'set "ec=3" & echo ... & exit /b !ec!'; $LASTEXITCODE
...
3

cmd.exe这边:

  • set "ec=3" 将变量 ec 设置为值 3

    • 将名称-值对括在 "..." 中并不是绝对必要的,但清楚地描述了值的结尾,并允许使用带有嵌入特殊字符的值,例如 &.

    • 变量的 value 以后可以引用为 %ec%up-front 扩展)或!ec!延迟 扩展,如果通过 setlocal enabledelayedexpansion 或命令行开关 /v 启用 - 参见 help setlocal

  • echo ... 是代表更多命令的示例命令

  • exit /b !ec!以变量ec的值作为退出码退出;请注意变量是如何通过 delayed 扩展被引用为 !ec! 而不是 %ec%,因为变量被设置为 作为同样的语句.

    • 是否使用/b(仅退出当前批处理文件)在这里没有区别;无论哪种方式,本例中的 exit 语句确定 cmd 实例的 进程退出代码

命令是顺序(无条件地一个接一个地执行),使用&运算符,作为单个语句的一部分。

在 PowerShell 方面:

  • PowerShell 类似于 cmd.exe&; 语句分隔符 - 它允许您将多个语句放在一行中。

  • $LASTEXITCODE 是包含最近执行的外部程序的进程退出代码的自动 PowerShell 变量,在本例中为 cmd.exe 的,值为 3.


Does anyone have any idea why the command SET %ERRORLEVEL% = 4 does not work?

总结问题评论中的有用信息:

  • 从根本上说,不要尝试设置 动态(伪)环境变量 %ERRORLEVEL% -它由 cmd.exe 自动 维护以反映最近命令的退出代码 - 请参阅底部。

  • 不要在 cmd.exe 变量赋值中将 space 放在 = 周围:

    • space(s)之前=成为变量名的一部分.
    • space(s)成为部分值.
  • 不要将目标变量名括在%...%中(除非你想间接设置一个变量,通过另一个变量,其 value 包含要分配给的变量的名称)。

set %ERRORLEVEL% = 4

%ERRORLEVEL% 在命令序列的开头反映了 0,上面的赋值创建了一个变量 字面上命名的 (即是 %ERRORLEVEL% 后跟单个 space 的值),其值为  4(即单个 space 后跟 4)。


cmd.exe中的变量:

基本上,除了下面讨论的例外情况,cmd.exe 中的变量都是环境变量

与 Bash 和 PowerShell 等 shell 不同, 没有 单独的名称 space shell-local 子进程 可见的变量。

这具有以下含义:

  • 预定义的持久环境变量如%Path%与您使用SET命令定义的自定义变量共享相同的名称space,因此您必须注意名称冲突。

  • 类似地,child 从您的 cmd.exe 会话/批处理文件中处理您 运行 inherit 您在会话中创建的自定义变量。

    • 请注意,使用 setlocal 不会 改变它; setlocal 是一种 cmd 内部作用域机制,允许您 控制自定义环境变量的生命周期 ,方法是将它们本地化到其中的作用域(批处理文件) setlocal 被调用,并通过随后的 endlocal 调用或隐式地在封闭批处理文件的末尾删除它们。

自定义变量是仅限进程的环境变量,超出了 cmd.exe 进程的范围; 持久性 环境变量定义必须通过 注册表 创建和修改,例如使用 setx.exe 实用程序。

除了预定义(持久)环境变量和自定义(仅限会话)环境变量外,cmd.exe 维护 动态 伪环境变量例如 %ERRORLEVEL%%RANDOM%(见下面的列表):

  • 这些伪环境变量具有动态值,由cmd.exe自身维护...

  • ...它们对子进程可见。

注意:严格来说,这些动态变量仅在打开所谓的命令扩展时启用,但确实如此默认情况下(您可以使用[=禁用它们71=],但这是不明智的)。

因为这些动态变量严格来说不是子进程继承副本的进程环境的一部分,所以它们不是环境变量, 尽管 help SET 有点混淆地称它们为 动态环境变量.

您不应该(也不能)修改这些变量。

如果你尝试,真正发生的是你 shadow(覆盖)这些伪变量 real,自定义环境变量,根据定义有 static 值。

以后依赖于该名称的变量以具有其通常的动态行为的代码可能会出现故障。

动态变量列表,在Windows 10 上通过help SET 检索(强调已添加):

If Command Extensions are enabled, then there are several dynamic environment variables that can be expanded but which don't show up in the list of variables displayed by SET. These variable values are computed dynamically each time the value of the variable is expanded. If the user explicitly defines a variable with one of these names, then that definition will override the dynamic one described below:

  • %CD% - expands to the current directory string.
  • %DATE% - expands to current date using same format as DATE command.
  • %TIME% - expands to current time using same format as TIME command.
  • %RANDOM% - expands to a random decimal number between 0 and 32767.
  • %ERRORLEVEL% - expands to the current ERRORLEVEL value
  • %CMDEXTVERSION% - expands to the current Command Processor Extensions version number.
  • %CMDCMDLINE% - expands to the original command line that invoked the Command Processor.
  • %HIGHESTNUMANODENUMBER% - expands to the highest NUMA node number on this machine.