【问题标题】:How to return non zero exit code from a Powershell module function without closing the powershell console?如何在不关闭 Powershell 控制台的情况下从 Powershell 模块函数返回非零退出代码?
【发布时间】:2019-11-21 05:52:22
【问题描述】:

我的 powershell 模块有一个函数,我希望它返回一个非零退出代码。但是,作为一个模块函数,当我运行Import-Module 时,它会加载到 powershell 控制台的上下文中。所以,当函数执行exit 1 - 噗,进入控制台窗口!

至少,这就是我解释它在退出时关闭 powershell 窗口的方式。

那么,如何在不杀死导入模块的控制台的情况下以非零退出代码退出 ps 模块函数?

附言

我确实注意到关于这个主题的几个关于 SO 的问题,但似乎没有人研究这个特殊情况。

编辑 1

我想提供一些背景信息。我有一个具有很多功能的 PS 模块。其中一些在 Azure DevOps yaml 构建脚本中按原样使用。后者知道识别非零退出代码并中止管道,因此没有必要从函数中抛出来中止流程。

但是,如果我想从控制台调用该函数,例如为了快速测试某些东西并以非零代码退出,整个控制台窗口都关闭了。这非常烦人。

有时有一种解决方法。所以,而不是这个代码:

dotnet build ...
$ExitCode = $LastExitCode
DoSomethingInAnyCase()
if ($ExitCode)
{
    exit $ExitCode
}

我们可以有以下版本:

try
{
    dotnet build ...
}
finally
{
    DoSomethingInAnyCase()
}

两个版本都会正确返回正确的退出代码,但因为第二个版本没有明确的exit 语句,所以它不会关闭控制台。

【问题讨论】:

  • 您要解决什么问题(需要非零退出代码)?
  • 我想在没有明确的 throw 语句的情况下指示失败。
  • 为什么?抛出异常有什么问题?
  • 屏幕上的垃圾太多了。我确实经常使用它,但我想知道退出代码,因此问题。
  • 我正在努力了解您的目标。模块实现在当前范围内执行的功能。函数不会更改退出代码,因为它们仅由进程或脚本设置。虽然我猜你可以写& $Env:ComSpec /c exit n?

标签: powershell


【解决方案1】:

您必须设置 $global:LASTEXITCODE 才能设置退出代码,但请注意,PowerShell 函数 并不是真的要设置退出代码,只有 脚本,而后者仅用于在通过 PowerShell 调用时通过 PowerShell 进程自己的退出代码向外界报告退出代码例如,它(CLI powershell.exe 用于 Windows PowerShell,pwsh 用于 PowerShell Core)来自构建工具、计划任务或其他 shell。

还要注意直接设置$global:LASTEXITCODE

  • 不会使 $?(自动成功状态变量)反映 $false 在调用者的上下文中,exit <nonzero-value> 从脚本中执行的方式以及调用报告错误的外部程序的方式非零退出代码。

  • 不足以使 PowerShell 进程作为一个整体报告此退出代码。

简而言之:所有这些好处是调用者可以在调用您的函数后检查$LASTEXITCODE,就像调用外部程序一样。。 p>


通常,退出代码是一个进程间概念,不太适合 PowerShell 的进程内世界。

有关 PowerShell 中的退出代码的详细信息,请参阅this post


PowerShell 的退出代码模拟是 $?,它是自动的布尔成功状态变量($true$false),它反映了 PowerShell 命令在之后立即成功。
(如果该命令是外部程序调用,则退出代码0$? 设置为$true,并且任何非零值将其设置为$false

事实证明,设置那个才是你真正要问的。

从 PowerShell Core 7.0.0-preview.5 开始,您无法直接设置 $?

目前,只有这些方法可以让$? 在调用者的范围内反映$false,相反,您不能始终确保它是$true

  • 脚本:使用exit <nonzero-integer>退出脚本

  • 来自 cmdlet 或函数(也包括脚本):

    • 引发脚本终止错误 (Throw) 或语句终止错误 ($PSCmdlet.ThrowTerminatingError()) - 后者仅在高级函数和脚本中可用。

    • 使用 $PSCmdlet.WriteError() 将错误写入 PowerShell 的错误流 - 后者仅在 高级 函数和脚本中可用。

      • 请注意,目前这出乎意料地应用于Write-Error cmdlet - 请参阅this GitHub issue

请注意,这两种技术都会引发错误

因为这听起来正是您要避免的,您必须等到实现设置$? 直接的功能

The decision to implement this ability has been made,但具体什么时候实施还不清楚。

【讨论】:

    【解决方案2】:

    解决方法:运行cmd.exe 并在退出函数之前设置您想要的任何退出代码。示例:

    function Test-Function {
      $cmd = Join-Path ([Environment]::GetFolderPath([Environment+SpecialFolder]::System)) "cmd.exe"
      & $cmd /c exit 3
      # $LASTEXITCODE will be set to 3
    }
    

    【讨论】:

      猜你喜欢
      • 2011-09-01
      • 2016-05-20
      • 1970-01-01
      • 1970-01-01
      • 2019-02-25
      • 1970-01-01
      • 2016-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多