捕获FULL异常消息

Jus*_*Guy 48 powershell exception-handling exception

考虑:

Invoke-WebRequest $sumoApiURL -Headers @{"Content-Type"= "application/json"} -Credential $cred -WebSession $webRequestSession -Method post -Body $sumojson -ErrorAction Stop
Run Code Online (Sandbox Code Playgroud)

这会引发以下异常:

在此输入图像描述

如何完全捕获它或至少过滤掉"已存在同名资源"?

使用$_.Exception.GetType().FullName收益率

System.Net.WebException

$_.Exception.Message给出

远程服务器返回错误:(400)错误请求.

Ans*_*ers 88

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
Run Code Online (Sandbox Code Playgroud)

如果您只想在catch块中显示错误消息,则可以简单地回显当前对象变量(在该点保存错误):

try {
  ...
} catch {
  $_
}
Run Code Online (Sandbox Code Playgroud)

如果您需要使用Write-Host带有格式化字符串的彩色输出,如上所述:

try {
  ...
} catch {
  ...
  Write-Host -Foreground Red -Background Black ($formatstring -f $fields)
}
Run Code Online (Sandbox Code Playgroud)

话虽如此,通常你不想只是在异常处理程序中显示错误消息(否则-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
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您要提取的信息似乎在$_.ErrorDetails.Message.如果你有一个对象或一个JSON字符串,我不太清楚,但你应该能够$_.ErrorDetails通过运行获得有关成员的类型和值的信息

$_.ErrorDetails | Get-Member
$_.ErrorDetails | Format-List *
Run Code Online (Sandbox Code Playgroud)

如果$_.ErrorDetails.Message是对象,您应该能够获得如下消息字符串:

$_.ErrorDetails.Message.message
Run Code Online (Sandbox Code Playgroud)

否则你需要先将JSON字符串转换为对象:

$_.ErrorDetails.Message | ConvertFrom-Json | Select-Object -Expand message
Run Code Online (Sandbox Code Playgroud)

根据您正在处理的错误类型,特定类型的异常可能还包括有关手头问题的更具体信息.例如,在您的情况下WebException,除了错误消息($_.Exception.Message)之外,您还有一个来自服务器的实际响应:

PS C:\> $e.Exception | Get-Member

   TypeName: System.Net.WebException

Name             MemberType Definition
----             ---------- ----------
Equals           Method     bool Equals(System.Object obj), bool _Exception.E...
GetBaseException Method     System.Exception GetBaseException(), System.Excep...
GetHashCode      Method     int GetHashCode(), int _Exception.GetHashCode()
GetObjectData    Method     void GetObjectData(System.Runtime.Serialization.S...
GetType          Method     type GetType(), type _Exception.GetType()
ToString         Method     string ToString(), string _Exception.ToString()
Data             Property   System.Collections.IDictionary Data {get;}
HelpLink         Property   string HelpLink {get;set;}
HResult          Property   int HResult {get;}
InnerException   Property   System.Exception InnerException {get;}
Message          Property   string Message {get;}
Response         Property   System.Net.WebResponse Response {get;}
Source           Property   string Source {get;set;}
StackTrace       Property   string StackTrace {get;}
Status           Property   System.Net.WebExceptionStatus Status {get;}
TargetSite       Property   System.Reflection.MethodBase TargetSite {get;}

它为您提供如下信息:

PS C:\> $e.Exception.Response

IsMutuallyAuthenticated : False
Cookies                 : {}
Headers                 : {Keep-Alive, Connection, Content-Length, Content-T...}
SupportsHeaders         : True
ContentLength           : 198
ContentEncoding         :
ContentType             : text/html; charset=iso-8859-1
CharacterSet            : iso-8859-1
Server                  : Apache/2.4.10
LastModified            : 17.07.2016 14:39:29
StatusCode              : NotFound
StatusDescription       : Not Found
ProtocolVersion         : 1.1
ResponseUri             : http://www.example.com/
Method                  : POST
IsFromCache             : False

由于并非所有异常都具有完全相同的属性集,因此您可能希望针对特定异常使用特定处理程序:

try {
  ...
} catch [System.ArgumentException] {
  # handle argument exceptions
} catch [System.Net.WebException] {
  # handle web exceptions
} catch {
  # handle all other exceptions
}
Run Code Online (Sandbox Code Playgroud)

如果无论是否发生错误都需要执行操作(清除任务,如关闭套接字或数据库连接),可以finally在异常处理后将它们放入块中:

try {
  ...
} catch {
  ...
} finally {
  # cleanup operations go here
}
Run Code Online (Sandbox Code Playgroud)

  • 如果您认为PowerShell的默认格式错误旨在激怒C#工程师并鼓励他们将PowerShell投入黑洞,请进行投票. (4认同)

Gor*_*gus 17

选项 1:简单但有效,足以满足大多数用途

try {1/0} catch { $_ | Format-List * -Force | Out-String }

结果是:

PSMessageDetails      :
Exception             : System.Management.Automation.RuntimeException: Attempted to divide by zero. ---> System.DivideByZeroException: Attempted to divide by zero.
                           --- End of inner exception stack trace ---
                           at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
                           at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
                           at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
                           at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
TargetObject          :
CategoryInfo          : NotSpecified: (:) [], RuntimeException
FullyQualifiedErrorId : RuntimeException
ErrorDetails          :
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {}

Run Code Online (Sandbox Code Playgroud)

选项 2:同时打印调用信息

try {1/0} catch { $_ | Format-List * -Force | Out-String ; $_.InvocationInfo | Format-List * -Force | Out-String }

结果是:

PSMessageDetails      :
Exception             : System.Management.Automation.RuntimeException: Attempted to divide by zero. ---> System.DivideByZeroException: Attempted to divide by zero.
                           --- End of inner exception stack trace ---
                           at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
                           at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
                           at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
                           at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
TargetObject          :
CategoryInfo          : NotSpecified: (:) [], RuntimeException
FullyQualifiedErrorId : RuntimeException
ErrorDetails          :
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {}





MyCommand             :
BoundParameters       : {}
UnboundArguments      : {}
ScriptLineNumber      : 1
OffsetInLine          : 6
HistoryId             : -1
ScriptName            :
Line                  : try {1/0} catch { $_ | Format-List * -Force | Out-String ; $_.InvocationInfo | Format-List * -Force | Out-String }
PositionMessage       : At line:1 char:6
                        + try {1/0} catch { $_ | Format-List * -Force | Out-String ; $_.Invocat ...
                        +      ~~~
PSScriptRoot          :
PSCommandPath         :
InvocationName        :
PipelineLength        : 0
PipelinePosition      : 0
ExpectingInput        : False
CommandOrigin         : Internal
DisplayScriptPosition :
Run Code Online (Sandbox Code Playgroud)

选项 3:以上两者加上所有内部异常

try {1/0} catch { $Exception = $_; $Exception | Format-List * -Force | Out-String ; $Exception.InvocationInfo | Format-List * -Force | Out-String ; for ($i = 0; $Exception; $i++, ($Exception = $Exception.InnerException)) { Write-Host ("$i" * 80) ; $Exception | Format-List * -Force | Out-String } }

PSMessageDetails      :
Exception             : System.Management.Automation.RuntimeException: Attempted to divide by zero. ---> System.DivideByZeroException: Attempted to divide by zero.
                           --- End of inner exception stack trace ---
                           at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
                           at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
                           at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
                           at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
TargetObject          :
CategoryInfo          : NotSpecified: (:) [], RuntimeException
FullyQualifiedErrorId : RuntimeException
ErrorDetails          :
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {}





MyCommand             :
BoundParameters       : {}
UnboundArguments      : {}
ScriptLineNumber      : 1
OffsetInLine          : 6
HistoryId             : -1
ScriptName            :
Line                  : try {1/0} catch { $Exception = $_; $Exception | Format-List * -Force | Out-String ; $Exception.InvocationInfo | Format-List * -Force | Out-String ; for ($i = 0; $Exception;
                        $i++, ($Exception = $Exception.InnerException)) { Write-Host ("$i" * 80) ; $Exception | Format-List * -Force | Out-String  }  }
PositionMessage       : At line:1 char:6
                        + try {1/0} catch { $Exception = $_; $Exception | Format-List * -Force  ...
                        +      ~~~
PSScriptRoot          :
PSCommandPath         :
InvocationName        :
PipelineLength        : 0
PipelinePosition      : 0
ExpectingInput        : False
CommandOrigin         : Internal
DisplayScriptPosition :




00000000000000000000000000000000000000000000000000000000000000000000000000000000


PSMessageDetails      :
Exception             : System.Management.Automation.RuntimeException: Attempted to divide by zero. ---> System.DivideByZeroException: Attempted to divide by zero.
                           --- End of inner exception stack trace ---
                           at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
                           at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
                           at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
                           at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
TargetObject          :
CategoryInfo          : NotSpecified: (:) [], RuntimeException
FullyQualifiedErrorId : RuntimeException
ErrorDetails          :
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {}
Run Code Online (Sandbox Code Playgroud)


mms*_*eng 12

我不断回到这些问题上,试图找出我感兴趣的数据究竟隐藏在真正单一的 ErrorRecord 结构中的何处。几乎所有的答案都给出了有关如何提取某些数据位的零碎说明。

但是我发现转储整个对象非常有帮助,ConvertTo-Json这样我就可以在一个易于理解的布局中直观地看到所有内容。

    try {
        Invoke-WebRequest...
    }
    catch {
        Write-Host ($_ | ConvertTo-Json)
    }
Run Code Online (Sandbox Code Playgroud)

使用ConvertTo-Json-Depth参数来扩展更深的值,但在超过2:P的默认深度时要格外小心

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertto-json

  • “ConvertTo-Json”让我失望,因为“不支持字典的序列化或反序列化类型“System.Collections.ListDictionaryInternal”。键必须是字符串。`; 我通过使用“Out-String”得到了我需要的东西。 (3认同)

Jus*_*Guy 11

我找到了!

只需打印出$Error[0]最后一条错误消息.


Tim*_*Ker 5

你可以加:

-ErrorVariable errvar
Run Code Online (Sandbox Code Playgroud)

然后看看$errvar.


Tar*_*aif 5

以下对我来说很好

try {
    asdf
} catch {
    $string_err = $_ | Out-String
}

write-host $string_err
Run Code Online (Sandbox Code Playgroud)

结果如下所示,而不是使用ErrorRecord对象作为字符串

asdf : The term 'asdf' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Users\TASaif\Desktop\tmp\catch_exceptions.ps1:2 char:5
+     asdf
+     ~~~~
    + CategoryInfo          : ObjectNotFound: (asdf:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
Run Code Online (Sandbox Code Playgroud)