web-dev-qa-db-ja.com

最初のエラーでPowerShellスクリプトを停止するにはどうすればよいですか?

実行するコマンドのいずれかが失敗した場合(bashのset -eなど)、PowerShellスクリプトを停止します。 Powershellコマンド(New-Object System.Net.WebClient)とプログラム(.\setup.exe)の両方を使用しています。

211
Andres Riofrio

$ErrorActionPreference = "Stop"は、その方法の一部を提供します(つまり、これはコマンドレットに最適です)。

ただし、EXEの場合は、exeを呼び出すたびに$LastExitCodeを自分でチェックし、失敗したかどうかを判断する必要があります。残念ながら、Windowsでは、「成功」または「失敗」の終了コードを構成するものについてEXEが一貫していないため、PowerShellがここで役立つとは思わない。ほとんどが成功を示す0のUNIX標準に従いますが、すべてが成功するわけではありません。 このブログ投稿のCheckLastExitCode関数 をご覧ください。役に立つかもしれません。

255
Keith Hill

スクリプトの先頭でステートメント$ErrorActionPreference = "Stop"を使用して、これを実現できるはずです。

$ErrorActionPreferenceのデフォルト設定はContinueであるため、エラーが発生した後もスクリプトが継続して表示されます。

61
goric

悲しいことに、 New-RegKeyやClear-Diskなどのバグのあるコマンドレットのため 、これらの答えはどれも十分ではありません。現在、健全性を維持するために、PowerShellスクリプトの先頭にある次の行に決めています。

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction']='Stop'

そして、ネイティブコールはこの処理を取得します。

native_call.exe
$native_call_success = $?
if (-not $native_call_success)
{
    throw 'error making native call'
}

そのネイティブコールパターンは徐々に一般的になりつつあるため、より簡潔にするためのオプションを検討する必要があります。私はまだPowershellの初心者なので、提案を歓迎します。

11
aggieNick02

Powershell関数とexeの呼び出しでわずかに異なるエラー処理が必要であり、スクリプトの呼び出し元に失敗したことを必ず通知する必要があります。ライブラリPsakeのExecの上に構築すると、以下の構造を持つスクリプトはすべてのエラーで停止し、ほとんどのスクリプトのベーステンプレートとして使用できます。

Set-StrictMode -Version latest
$ErrorActionPreference = "Stop"


# Taken from psake https://github.com/psake/psake
<#
.SYNOPSIS
  This is a helper function that runs a scriptblock and checks the PS variable $lastexitcode
  to see if an error occcured. If an error is detected then an exception is thrown.
  This function allows you to run command-line programs without having to
  explicitly check the $lastexitcode variable.
.EXAMPLE
  exec { svn info $repository_trunk } "Error executing SVN. Please verify SVN command-line client is installed"
#>
function Exec
{
    [CmdletBinding()]
    param(
        [Parameter(Position=0,Mandatory=1)][scriptblock]$cmd,
        [Parameter(Position=1,Mandatory=0)][string]$errorMessage = ("Error executing command {0}" -f $cmd)
    )
    & $cmd
    if ($lastexitcode -ne 0) {
        throw ("Exec: " + $errorMessage)
    }
}

Try {

    # Put all your stuff inside here!

    # powershell functions called as normal and try..catch reports errors 
    New-Object System.Net.WebClient

    # call exe's and check their exit code using Exec
    Exec { setup.exe }

} Catch {
    # tell the caller it has all gone wrong
    $Host.SetShouldExit(-1)
    throw
}
9
alastairtree

@alastairtreeからの answer のわずかな変更:

function Invoke-Call {
    param (
        [scriptblock]$ScriptBlock,
        [string]$ErrorAction = $ErrorActionPreference
    )
    & @ScriptBlock
    if (($lastexitcode -ne 0) -and $ErrorAction -eq "Stop") {
        exit $lastexitcode
    }
}

Invoke-Call -ScriptBlock { dotnet build . } -ErrorAction Stop

主な違いは次のとおりです。

  1. 動詞-名詞(Invoke-Commandを模倣)を使用します
  2. カバーの下で call operator を使用することを意味します
  3. mimics組み込みコマンドレットからの-ErrorActionの動作
  4. 新しいメッセージで例外をスローするのではなく、同じ終了コードで終了します
5
Lucas

私は同じものを探してここに来ました。 $ ErrorActionPreference = "Stop"は、終了する前にエラーメッセージ(一時停止)を表示したい場合、すぐにシェルを強制終了します。バッチの感度に頼る:

IF %ERRORLEVEL% NEQ 0 pause & GOTO EOF

これは、私の特定のps1スクリプトでもほぼ同じように機能することがわかりました。

Import-PSSession $Session
If ($? -ne "True") {Pause; Exit}
2
harvey263

私はPowerShellの初心者ですが、これは最も効果的であるようです:

doSomething -arg myArg
if (-not $?) {throw "Failed to doSomething"}
0
Peter L