PowerShell和进程退出代码

PowerShell和进程退出代码,powershell,error-handling,exit-code,Powershell,Error Handling,Exit Code,这个自我回答的问题试图解决在PowerShell中处理问题的两个不同方面: 在PowerShell代码中,如何查询外部进程(对外部程序的调用)设置的退出代码,以及这些退出代码如何与PowerShell的错误处理集成 当其他人通过其CLI(PowerShell Core)/(Windows PowerShell)调用PowerShell时,是什么决定了PowerShell进程的退出代码,该代码将成功与失败传达给调用进程(例如,可能是生成/CI/自动化服务器任务、计划任务或其他shell) 自Po

这个自我回答的问题试图解决在PowerShell中处理问题的两个不同方面:

  • 在PowerShell代码中,如何查询外部进程(对外部程序的调用)设置的退出代码,以及这些退出代码如何与PowerShell的错误处理集成

  • 当其他人通过其CLI(PowerShell Core)/(Windows PowerShell)调用PowerShell时,是什么决定了PowerShell进程的退出代码,该代码将成功与失败传达给调用进程(例如,可能是生成/CI/自动化服务器任务、计划任务或其他shell)

自PowerShell[Core]7.1.0-preview.6起的当前版本

PowerShell内部使用退出代码: PowerShell内部,本机PowerShell命令通常在进程内运行,运行外部程序的子进程的退出代码的作用非常有限

  • 本机PowerShell命令通常不会设置退出代码,也不会对其进行操作

  • PowerShell与退出代码有一个抽象对应项

  • 它反映了最近执行的命令是否有任何错误,但实际上很少使用它,这主要是因为在6.x版本之前,在
    中包含一个命令似乎无关紧要(…)
    $?
    重置为
    $true
    -请参阅-并且因为在用户函数中使用
    写入错误
    不会将
    $?
    设置为
    $false
    -请参阅;不过,最终还是会有一个未来的版本

  • $?
    还反映(紧接着)外部程序报告的退出代码是
    0
    (信号成功,使
    $?
    报告
    $true
    )还是非零退出代码(通常是信号失败,使
    $?
    $false
    ),正是自动
    $LASTEXICODE
    变量
    将特定退出代码作为整数包含,并且该值将保留,直到在同一会话中调用另一个外部程序(如果有)为止

    • 注意事项:由于
      cmd.exe
      的怪癖,批处理文件的退出代码无法可靠报告,但您可以使用
      cmd/c…`&退出
      -请参阅;此外,还建议将此解决方案构建到PowerShell本身中
    • 此外,在v7.1之前和之后,
      $?
      如果外部程序报告退出代码
      0
      ,同时也生成stderr输出,并且还有涉及
      2>
      *>
      的PowerShell重定向,则会报告误报-请参阅和;自PowerShell PowerShell Core 7.2.0-preview.4起;更正的行为可作为
      PSNotApplyErrorActionToStderr
      提供
  • 与PowerShell本机命令报告的终止错误或非终止错误不同,外部程序的非零退出代码不能由
    $ErrorActionPreference
    首选项变量自动执行;也就是说,当外部程序报告非零退出代码时,不能使用该变量使外部程序的stderr输出静音,更重要的是,也不能通过value
    “Stop”
    选择中止脚本

    • 中建议将外部程序更好地集成到PowerShell的错误处理中

如何控制从外部调用PowerShell时,哪些PowerShell报告为其退出代码: 设置至少传达成功(
0
)与失败(通常为非零)的退出代码是让外部调用方知道您的PowerShell代码是否整体成功的重要机制,例如,当通过PowerShell CLI(命令行界面)从计划任务或自动化服务器(如Jenkins)调用PowerShell[Core]与Windows PowerShell时

CLI提供了两种执行PowerShell代码的方法,您可以使用
exit
设置退出代码,其中
是所需的退出代码:

  • -File[args…]
    需要执行脚本文件(
    *.ps1
    )的路径,可以选择后跟参数

    • 直接在这样一个脚本文件中执行
      exit
      (而不是在从该脚本调用的另一个脚本中执行),会使PowerShell进程将其退出代码报告为
  • -Command
    需要包含一个或多个PowerShell命令的字符串

    • 为了安全起见,请使用
      exit
      作为该命令字符串的直接部分-通常作为最后一条语句
如果您的代码是从通过退出代码检查成功的工具调用的,请确保所有代码路径都明确使用
exit
终止。

警告:如果PowerShell进程由于未处理的脚本终止错误而终止-无论是使用
-File
还是
-Command
调用CLI,退出代码始终为
1

  • 脚本终止(致命)错误是由PowerShell代码通过
    throw
    语句生成的,或者通过
    -ErrorAction Stop
    $ErrorActionPreference='Stop'
    升级不太严重的本机PowerShell错误,或者通过按Ctrl-C强制终止脚本生成的

  • 如果退出代码
    1
    不够具体(通常是这样,因为通常只需要沟通成功与失败),您可以将代码包装在
    try
    /
    catch
    语句中,并使用
    catch
    块中的
    退出

PowerShell如何设置其进程退出的确切规则