1. ホーム
  2. powershell

[解決済み] FULL例外メッセージの捕捉

2023-05-26 01:15:22

質問

考えてみましょう。

Invoke-WebRequest $sumoApiURL -Headers @{"Content-Type"= "application/json"} -Credential $cred -WebSession $webRequestSession -Method post -Body $sumojson -ErrorAction Stop

これは以下のような例外を投げます。

どうすれば完全に捕らえることができますか、少なくとも "同じ名前のリソースがすでに存在しています." をフィルタリングできますか?

使用方法 $_.Exception.GetType().FullName

System.Net.WebException

$_.Exception.Message が与える

リモートサーバーがエラーを返しました。(400) 不正なリクエストです。

どのように解決するのですか?

PowerShellにおけるエラーと例外は、構造化されたオブジェクトです。コンソールに表示されるエラーメッセージは、実際には、エラー/例外オブジェクトのいくつかの要素からの情報を含むフォーマットされたメッセージです。このように自分で(再)構築することができます。

$formatstring = "{0} : {1}`n{2}`n" +
                "    + CategoryInfo          : {3}`n" +
                "    + FullyQualifiedErrorId : {4}`n"
$fields = $_.InvocationInfo.MyCommand.Name,
          $_.ErrorDetails.Message,
          $_.InvocationInfo.PositionMessage,
          $_.CategoryInfo.ToString(),
          $_.FullyQualifiedErrorId

$formatstring -f $fields

もし、エラーメッセージを catch ブロックに表示させたい場合は、現在のオブジェクト変数 (その時点のエラーを保持している) を echo するだけでよいでしょう。

try {
  ...
} catch {
  $_
}

色つきの出力が必要な場合は Write-Host を使い、上記のようにフォーマットされた文字列で出力します。

try {
  ...
} catch {
  ...
  Write-Host -Foreground Red -Background Black ($formatstring -f $fields)
}

とはいえ、通常は例外ハンドラでエラーメッセージをそのまま表示したいとは思わないでしょう(そうでない場合は -ErrorAction Stop は無意味になります)。構造化されたエラー/例外オブジェクトは、より良いエラー制御のために使用できる追加情報を提供します。例えば、あなたが $_.Exception.HResult には実際のエラー番号が書かれています。 $_.ScriptStackTrace$_.Exception.StackTrace で、デバッグ時にスタックトレースを表示できるようにします。 $_.Exception.InnerException を使用すると、エラーに関する追加情報を含むネストされた例外にアクセスできるようになります (トップレベルの PowerShell エラーはある程度一般的なものである可能性があります)。これらのネストされた例外は、次のような方法で展開することができます。

$e = $_.Exception
$msg = $e.Message
while ($e.InnerException) {
  $e = $e.InnerException
  $msg += "`n" + $e.Message
}
$msg

あなたの場合、抽出したい情報は $_.ErrorDetails.Message . そこにオブジェクトがあるのか JSON 文字列があるのか、私にはよく分かりませんが、以下のメンバーの型と値に関する情報を得ることができるはずです。 $_.ErrorDetails のメンバーの型と値に関する情報を得ることができるはずです。

$_.ErrorDetails | Get-Member
$_.ErrorDetails | Format-List *

もし $_.ErrorDetails.Message がオブジェクトであれば、このようにメッセージ文字列を得ることができるはずです。

$_.ErrorDetails.Message.message

を使用する場合は、まずJSON文字列をオブジェクトに変換する必要があります。

$_.ErrorDetails.Message | ConvertFrom-Json | Select-Object -Expand message

どのような種類のエラーを処理しているかによりますが、特定のタイプの例外は、目下の問題についてのより具体的な情報を含むかもしれません。例えばあなたの場合 WebException があり、エラーメッセージに加えて ( $_.Exception.Message ) には、サーバからの実際のレスポンスが含まれます。

PS C:\> 

$e.Exception | Get-Member



   TypeName: System.Net.WebException

名前 MemberType 定義
---- ---------- ----------
Equals Method bool Equals(System.Object obj), bool _Exception.E....
GetBaseException メソッド System.Exception GetBaseException(), System.ExcepException.GetBase...
GetHashCode Method int GetHashCode(), int _Exception.GetHashCode()
GetObjectDataメソッド void GetObjectData(System.Runtime.Serialization.S....
GetType Method type GetType()、type _Exception.GetType()
ToStringメソッド string ToString()、string _Exception.ToString()
Data Property System.Collections.IDictionary Data {get;}.
HelpLink Property 文字列 HelpLink {get;set;}.
HResult Property int HResult {get;}.
InnerException Property System.Exception InnerException {get;}。
Message Property 文字列 Message {get;}.



Response Property System.Net.WebResponse Response {get;}。



ソースプロパティ string Source {get;set;}.
StackTrace Property 文字列 StackTrace {get;} Status Property System.Net.WebExceptionStatus Status {get;}。
TargetSite Property System.Reflection.MethodBase TargetSite {get;}。

というように、このような情報を得ることができます。

PS C:\> 


$e.Exception.Response(応答



IsMutuallyAuthenticated : False
クッキー
Headers : {Keep-Alive, Connection, Content-Length, Content-T...}.
SupportsHeaders : True
コンテンツの長さ : 198
ContentEncoding :
ContentType : text/html; charset=iso-8859-1
文字セット : iso-8859-1
サーバー : Apache/2.4.10
最終修正 : 2016年7月17日 14:39:29
StatusCode : NotFound
StatusDescription : Not Found(見つかりません
プロトコルバージョン : 1.1
ResponseUri : http://www.example.com/
メソッド : POST
IsFromCache : False

すべての例外が全く同じプロパティを持つわけではないので、特定の例外に対して特定のハンドラを使用したい場合があります。

try {
  ...
} catch [System.ArgumentException] {
  # handle argument exceptions
} catch [System.Net.WebException] {
  # handle web exceptions
} catch {
  # handle all other exceptions
}

エラーが発生したかどうかに関係なく行う必要のある操作(ソケットやデータベース接続のクローズなどのクリーンアップタスク)がある場合、それらを finally ブロックに入れることができます。

try {
  ...
} catch {
  ...
} finally {
  # cleanup operations go here
}