如何在不关闭 powershell 控制台的情况下从 Powershell 模块函数返回非零退出代码?

mar*_*ark 3 powershell

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

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

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

聚苯乙烯

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

编辑1

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

但是,如果我想从控制台调用该函数,例如快速测试某些内容并且它以非零代码退出,则整个控制台窗口将关闭。这非常烦人。

有时有一个解决方法。所以,代替这段代码:

dotnet build ...
$ExitCode = $LastExitCode
DoSomethingInAnyCase()
if ($ExitCode)
{
    exit $ExitCode
}
Run Code Online (Sandbox Code Playgroud)

我们可以有以下版本:

try
{
    dotnet build ...
}
finally
{
    DoSomethingInAnyCase()
}
Run Code Online (Sandbox Code Playgroud)

两个版本都会正确返回正确的退出代码,但由于第二个版本没有显式exit语句,因此它不会关闭控制台。

mkl*_*nt0 6

您必须进行设置$global:LASTEXITCODE才能设置退出代码,但请注意,PowerShell函数实际上并不意味着设置退出代码,而只是脚本,而后者仅用于通过 PowerShell 进程向外界报告退出代码'例如,当从构建工具、计划任务或其他 shell通过 PowerShell(powershell.exe对于 Windows PowerShell 的CLI,对于 PowerShell Core)调用 PowerShell 时,可以使用自己的退出代码。pwsh

$global:LASTEXITCODE另请注意,直接设置:

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

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

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


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

有关 PowerShell 中退出代码的更多信息,请参阅此帖子


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

事实证明,设置这才是您真正想要问的。

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

目前,这些是导致在调用者范围内$?反映的唯一方法,相反,您不能始终确保它是:$false$true

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

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

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

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

      • 请注意,这意外地当前不适用于cmdlet Write-Error- 请参阅此 GitHub 问题

请注意,这两种技术都不可避免地涉及发出错误

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

实施该能力的决定已经做出,但尚不清楚何时实施。