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

标签 powershell cmd exit-code errorlevel delayedvariableexpansion

我希望能够在 PowerShell 中运行的命令提示符脚本(即%ERRORLEVEL%)的开头将cmd /c环境变量(也称为“系统变量”)设置为任意值。每当人们想要设置%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%。我使用了延迟的命令执行(example here),但是在这里似乎没有任何麻烦。

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

如果您不是而不是能够使用SET环境变量,那么如何在如上所述的由&符号分隔的命令字符串(%ERRORLEVEL%)中将&设置为任意值?

最佳答案

如果要将最终退出代码存储在cmd.exe变量中,以便以后与exit一起使用,则不要尝试设置ERRORLEVEL ;相反,使用自定义变量名称;例如ec(用于 e xit c ode):

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

cmd.exe一侧:
  • set "ec=3"将变量ec设置为3
  • 严格地不需要在"..."中包含名称-值对,但可以清楚地描述值的结尾,并允许使用带有嵌入式特殊字符(例如&)的值。
  • 变量的值以后可以引用为%ec%(前扩展)或!ec!(延迟扩展,如果通过setlocal enabledelayedexpansion或通过命令行开关/v-参见help setlocal启用)
  • echo ...是代表其他命令
  • 的示例命令
  • exit /b !ec!退出,变量ec的值作为退出代码;请注意,由于延迟变量是在同一语句中设置的,因此必须通过延迟扩展将变量称为!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自动维护该变量以反射(reflect)最新命令的退出代码-请参阅底部。
  • 不要在=变量分配中的cmd.exe 周围放置空格:
  • =之前的空格成为变量名称的一部分。
  • 之后的空格成为值的一部分。
  • 请勿将目标变量名称包含在%...% 中(除非您要通过另一个变量(其值包含要分配给该变量的名称)来间接设置变量)。

  • set %ERRORLEVEL% = 4



    通过%ERRORLEVEL%在命令序列的开头反射(reflect)0,上述分配创建了一个字面名为(即%ERRORLEVEL%的值,后跟一个空格)的变量,其值是 4(即,一个空格后是4) )。
    cmd.exe中的变量:

    从根本上讲,除了下面讨论的异常(exception),cmd.exe中的变量都是环境变量

    与Bash和PowerShell这样的shell不同,对于子进程看不到的shell本地变量没有单独的命名空间。

    这具有以下含义:
  • 预定义的持久性环境变量(例如%Path%)与使用SET命令定义的自定义变量共享相同的 namespace ,因此您必须注意名称冲突。
  • 同样,从cmd.exe session /批处理文件运行的子进程将继承在 session 中创建的自定义变量。
  • 注意setlocal的使用不会改变它; setlocalcmd的一种内部作用域机制,通过将其本地化到调用setlocal的作用域(批处理文件),并通过后续的endlocal调用或隐式地在其上删除它们,可以控制自定义环境变量的生存期。封闭批处理文件的末尾。

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

    除了预定义(持久)环境变量和自定义(仅 session )环境变量外, cmd.exe维护动态伪环境变量,例如%ERRORLEVEL%%RANDOM% (请参见下面的列表):
  • 这些伪环境变量具有由cmd.exe本身维护的动态值...
  • ...,它们对子进程不可见。

  • 注意:严格来说,仅在打开所谓的命令扩展名的情况下才启用这些动态变量,但是默认情况下是正确的(您可以使用/E:OFF禁用它们,但这是不明智的选择)。

    因为这些动态变量严格来说并不是子进程继承其副本的流程环境的一部分,所以它们不是环境变量,即使 help SET在某种程度上将它们称为动态环境变量

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

    如果尝试,真正发生的是用真实的,自定义的环境变量(根据定义具有静态值)来遮盖(覆盖)这些伪变量。

    因此,依赖该名称的变量的后续代码将具有其通常的动态行为,因此可能会发生故障。

    动态变量的列表,在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.

    关于powershell - 如何在cmd/c中设置%ERRORLEVEL%?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60459093/

    相关文章:

    c - 如何将返回代码传递给 at_exit 函数

    regex - 替换参数,删除不应该删除的空格

    c# - 使用 Powershell 关闭 IE 中的事件选项卡

    batch-file - 通读每一行并使用批处理文件检查该行是否以特定字符串开头

    c - Windows 10可以用gcc编译C程序但是不会运行

    makefile - 有 make 命令退出 1

    perl - 从 Perl 运行命令时段错误消失

    Powershell 无法精确匹配文件夹全名

    python - tkinter Canvas 窗口无法从Powershell打开

    windows - 批处理脚本多选