Ответ 1
Ошибки и исключения в PowerShell являются структурированными объектами. Сообщение об ошибке, напечатанное на консоли, на самом деле является отформатированным сообщением с информацией из нескольких элементов объекта "ошибка/исключение". Вы можете (re-) построить его самостоятельно так:
$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
, вы можете просто повторить текущую переменную объекта (которая содержит ошибку в этой точке):
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 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
}
Если у вас есть операции, которые необходимо выполнить независимо от того, произошла ошибка или нет (задачи очистки, такие как закрытие сокета или соединение с базой данных), вы можете поместить их в блок finally
после обработки исключения:
try {
...
} catch {
...
} finally {
# cleanup operations go here
}