web-dev-qa-db-ja.com

Write-Error vs. Throwはいつ使用する必要がありますか?終了エラーと非終了エラー

PoshCode上のGet-WebFileスクリプトを見ると、 http://poshcode.org/3226 、私はこの奇妙な仕掛けに気付いた。

$URL_Format_Error = [string]"..."
Write-Error $URL_Format_Error
return

以下とは対照的に、この理由は何ですか?

$URL_Format_Error = [string]"..."
Throw $URL_Format_Error

またはさらに良い:

$URL_Format_Error = New-Object System.FormatException "..."
Throw $URL_Format_Error

私が理解しているように、終了しないエラーにはWrite-Errorを使用し、エラーを終了するにはThrowを使用する必要があるため、Write-Errorの後にReturnを使用しないでください。違いはありますか?

123
Bill Barry

ユーザーに重大ではないエラーを通知する場合は、Write-Errorを使用する必要があります。デフォルトでは、コンソールにエラーメッセージを赤色のテキストで出力するだけです。パイプラインまたはループの継続を停止しません。一方、Throwは、終了エラーと呼ばれるものを生成します。 throwを使用すると、パイプラインや現在のループが終了します。実際、trapまたはtry/catch構造体を使用して終了エラーを処理しない限り、すべての実行は終了します。

注意すべき点が1つあります。$ErrorActionPreference"Stop"に設定し、Write-Errorを使用すると終了エラーが発生しますです。

リンクしたスクリプトで、これを見つけます。

if ($url.Contains("http")) {
       $request = [System.Net.HttpWebRequest]::Create($url)
}
else {
       $URL_Format_Error = [string]"Connection protocol not specified. Recommended action: Try again using protocol (for example 'http://" + $url + "') instead. Function aborting..."
       Write-Error $URL_Format_Error
    return
   }

その関数の作成者は、その関数の実行を停止し、画面にエラーメッセージを表示したいのですが、スクリプト全体の実行を停止したくないようです。スクリプトの作成者はthrowを使用することもできましたが、関数を呼び出すときにtry/catchを使用する必要があることを意味します。

returnは、関数、スクリプト、またはスクリプトブロックである現在のスコープを終了します。これはコードで最もよく説明されています。

# A foreach loop.
foreach ( $i in  (1..10) ) { Write-Host $i ; if ($i -eq 5) { return } }

# A for loop.
for ($i = 1; $i -le 10; $i++) { Write-Host $i ; if ($i -eq 5) { return } }

両方の出力:

1
2
3
4
5

ここでの落とし穴の1つは、returnForEach-Objectを使用することです。予想されるような処理の中断はありません。

詳しくは:

160
Andy Arismendi

PowerShellの Write-Error コマンドレットと throw キーワードの主な違いは、前者は単にprints標準エラーストリーム(stderr) へのテキスト、後者は実際に実行中のコマンドの処理を終了しますまたは、関数thenは、PowerShellがエラーに関する情報をコンソールに送信することによって処理されます。

指定した例で、2つの異なる動作を確認できます。

$URL_Format_Error = [string]"..."
Write-Error $URL_Format_Error
return

この例では、returnキーワードがexplicitlyに追加され、エラーメッセージがコンソールに送信された後にスクリプトの実行が停止されます。一方、2番目の例では、returnによって終了が暗黙的に行われるため、throwキーワードは不要です。

$URL_Format_Error = New-Object System.FormatException "..."
Throw $URL_Format_Error
15

Write-Errorを使用すると、関数のコンシューマは-ErrorAction SilentlyContinue(または-ea 0)を使用してエラーメッセージを抑制することができます。 throwにはtry{...} catch {..}が必要です

Write-Errorでtry ... catchを使用するには:

try {
    SomeFunction -ErrorAction Stop
}
catch {
    DoSomething
}
7
Rynant

Andy Arismendiの回答への追加

Write-Error がプロセスを終了するかどうかは、$ErrorActionPreference設定に依存します。

自明ではないスクリプトの場合、$ErrorActionPreference = "Stop"推奨設定 で高速に失敗します。

「エラーに関するPowerShellのデフォルトの動作は、エラーが発生しても続行します...非常にVB6の「エラー時の再開」次のように感じます」

http://codebetter.com/jameskovacs/2010/02/25/the-exec-problem/ から)

ただし、Write-Error呼び出しは終了します。

Write-Error を他の環境設定に関係なく終了しないコマンドとして使用するには、 commonパラメーターを使用できます-ErrorActionと値Continue

 Write-Error "Error Message" -ErrorAction:Continue
5

コードの読み取りが正しければ、正解です。エラーの終了にはthrowを使用する必要があります。また、.NETタイプを扱う場合は、.NETの例外規則に従うことも役立ちます。

0
yzorg