Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
546 views
in Technique[技术] by (71.8m points)

error handling - Is there a powershell pattern for if($?) { }

I find myself chaining these a lot, eg:

do-cmd-one
if($?)
{
do-cmd-two
}
...

then at the end:

if(!$?)
{
   exit 1
}

I assume there's a pattern for this in powershell but I don't know it.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

PowerShell [Core] 7.0 introduced Bash-like && and || operators called pipeline-chain operators.

They will not be back-ported to Windows PowerShell, however, as the latter will generally see no new features.

In short, instead of:

do-cmd-one; if ($?) { do-cmd-two }

Note: As of PowerShell 7.1, the more robust formulation is actually
do-cmd-one; if ($LASTEXITCODE -eq 0) { do-cmd-two }, for the reasons explained in this answer.

you can now write:

do-cmd-one && do-cmd-two

&& (AND) and || (OR) implicitly operate on each command's implied success status, as reflected in automatic Boolean variable $?.

This will likely be more useful with external programs, whose exit codes unambiguously imply whether $? is $true (exit code 0) or $false (any nonzero exit code).

By contrast, for PowerShell commands (cmdlets) $? just reflects whether the command failed as a whole (a statement-terminating error occurred) or whether at least one non-terminating error was reported; the latter doesn't necessarily indicate overall failure.
However, there are plans to allow PowerShell commands to set $? directly, as a deliberate overall-success indicator.

Also note that the following do not work with && and ||:

  • PowerShell's Test-* cmdlets, because they signal the test result by outputting a Boolean rather than by setting $?; e.g.,
    Test-Path $somePath || Write-Warning "File missing" wouldn't work.

  • Boolean expressions, for the same reason; e.g.,
    $files.Count -gt 0 || write-warning 'No files found' wouldn't work.

See this answer for background information, and the discussion in this GitHub issue.


There's a syntax caveat: As of this writing, the following will not work:

do-cmd-one || exit 1 # !! Currently does NOT work

Instead, you're forced to wrap exit / return / throw statements in $(...), the so-called subexpression operator:

do-cmd-one || $(exit 1) # Note the need for $(...)

This GitHub issue discusses the reasons for this awkward requirement, which are rooted in the fundamentals of PowerShell's grammar.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...