try/catchコントロールの全体的な考え方は、エラーをスローしてスクリプトを停止するという既定のアクションではなく、終了エラーが発生した場合にスクリプトに何をすべきかを指示することです。catch ブロックがWrite-Hostを使用して端末にメッセージを表示するだけの場合、それがすべてのエラー処理であり、スクリプトはそこから続行されます。考えてみれば、エラーがキャッチされるたびにスクリプトが自動的に停止されると、 try/catchの目的が部分的に無効になります。
catchブロックでは、$ _は、 tryブロックからの終了エラーを表す ErrorRecord オブジェクトに設定されます( $error[0]に格納されるものと同じもの)。したがって、スクリプトを終了する最も簡単な方法は、 try/catchを使用していなかった場合にスローされるエラーを再スローすることです。
try {
Get-Content "c:\GarbageFileName.txt" -ErrorAction stop
} catch {
# Custom action to perform before terminating
throw $_
}
または、デフォルトの ErrorRecord の代わりにカスタム メッセージを表示する場合:
try {
Get-Content "c:\GarbageFileName.txt" -ErrorAction stop
} catch {
throw 'Custom error message'
}
または、エラーストリームにエラーをスローせずにカスタムエラー処理を終了した後に終了する場合は、Joost の回答で提案されているようにbreakを使用できます。
または、より洗練された独自の ErrorRecord オブジェクトを作成することもできます。ここで包括的にカバーするには大きすぎるトピックですが、 System.Management.Automation.ErrorRecordをグーグルで検索すると、構文に関する詳細情報を取得できます。これは、開始するためのスクリプトの 1 つからの例です ( SQL Server データベースに対して$query変数で定義された SQL クエリを実行する関数から)。
} catch {
$ErrorRecord = New-Object System.Management.Automation.ErrorRecord(
(New-Object Exception("Exception executing the query: $($_.Exception.InnerException.Message)")),
$query,
[System.Management.Automation.ErrorCategory]::InvalidArgument,
$null
)
$ErrorRecord.CategoryInfo.Reason = $_.CategoryInfo.Reason;
$ErrorRecord.CategoryInfo.Activity = $_.InvocationInfo.InvocationName;
$PSCmdlet.ThrowTerminatingError($ErrorRecord);
}
いくつかのメモ:
- カスタム ErrorRecord を作成する際に$_を使用していることがわかります。これには、 tryブロックでキャッチされた終了エラーに関連付けられた ErrorRecord オブジェクトが含まれていると述べました。カスタム ErrorRecord の対応するプロパティに割り当てて、デフォルトの ErrorRecord の一部を使用しながら、一部のエラー出力をカスタマイズするという考え方です。
- $PSCmdlet
[CmdletBinding()]
は、関数またはスクリプトの先頭で宣言した場合にのみ使用できます。それ以外の場合は、throw $ErrorRecord
カスタム エラーをスローするために使用できます。ただし、 $PSCmdlet.ThrowTerminatingErrorを使用すると、結果はよりコマンドレット スタイルになります。( throwは、エラーを生成した関数からの行を吐き出しますが、$PSCmdlet.ThrowTerminatingErrorは、関数が使用された呼び出しコンテキストからの行を提供します。複雑になりすぎずに意味のある方法で説明するのは困難です。しかし、実験してみれば、私の言いたいことがわかるでしょう。)
$ErrorActionPreference = "Stop"
ところで、を設定してから使用するのは冗長-ErrorAction Stop
です。設定変数はすべてのコマンドレットの既定のアクションを設定し、-ErrorActionスイッチは特定のコマンドレットの既定のアクションをオーバーライドするため、最初に既定を指定してから-ErrorActionを使用して、既定として設定した同じアクションを指定する必要はありません。 . おそらくやりたいことは、ただ除外すること$ErrorActionPreference = "Stop"
です。