Błędy i wyjątki w PowerShell są obiektami strukturyzowane. Komunikat o błędzie wyświetlony na konsoli jest w rzeczywistości sformatowaną wiadomością zawierającą informacje z kilku elementów obiektu błędu/wyjątku. Można (re) konstruowania go samodzielnie tak:
$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
Jeśli chcesz tylko komunikat o błędzie wyświetlany w bloku catch
można po prostu echo aktualną zmienną obiektu (który posiada błąd w tym punkcie):
try {
...
} catch {
$_
}
Jeśli potrzebujesz kolorowego wykorzystanie wyjścia Write-Host
z sformatowany ciąg w sposób opisany powyżej:
try {
...
} catch {
...
Write-Host -Foreground Red -Background Black ($formatstring -f $fields)
}
z powiedział, że zwykle ty don nie chcesz wyświetlać komunikatu o błędzie, jak to jest w obsłudze wyjątków (w przeciwnym razie -ErrorAction Stop
byłoby bezcelowe). Strukturalne obiekty błędów/wyjątków dostarczają dodatkowych informacji, których można użyć w celu lepszej kontroli błędów. Na przykład masz $_.Exception.HResult
z rzeczywistym numerem błędu. $_.ScriptStackTrace
i $_.Exception.StackTrace
, dzięki czemu można wyświetlić ślad stosu podczas debugowania. $_.Exception.InnerException
daje dostęp do zagnieżdżonych wyjątków, które często zawierają dodatkowe informacje o błędzie (błędy PowerShell na najwyższym poziomie mogą być nieco ogólne). Można rozwinąć te zagnieżdżone wyjątki z czymś takim:
$e = $_.Exception
$msg = $e.Message
while ($e.InnerException) {
$e = $e.InnerException
$msg += "`n" + $e.Message
}
$msg
W twoim przypadku informacja chcesz wyodrębnić wydaje się być w $_.ErrorDetails.Message
.To nie jest dla mnie jasne, jeśli obiekt lub ciąg tam JSON, ale powinieneś być w stanie uzyskać informacje na temat typów i wartości członków $_.ErrorDetails
uruchamiając
$_.ErrorDetails | Get-Member
$_.ErrorDetails | Format-List *
Jeśli $_.ErrorDetails.Message
jest obiektem ty powinny być w stanie uzyskać ciąg wiadomość tak:
$_.ErrorDetails.Message.message
inaczej trzeba przekonwertować ciąg JSON do obiektu pierwsze:
$_.ErrorDetails.Message | ConvertFrom-Json | Select-Object -Expand message
W zależności od rodzaju błędu, który obsługuje, wyjątki poszczególnych typów mogą również zawierać bardziej szczegółowe informacje na temat problemu. W twoim przypadku na przykład masz WebException
które oprócz komunikatu o błędzie ($_.Exception.Message
) zawiera rzeczywistą odpowiedź od serwera:
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;}
który dostarcza informacji jak ta:
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
Rejestracja nie wszystkie wyjątki mają dokładnie taki sam zestaw właściwości, z których mogą korzystać określone programy obsługi dla określonych wyjątków:
try {
...
} catch [System.ArgumentException] {
# handle argument exceptions
} catch [System.Net.WebException] {
# handle web exceptions
} catch {
# handle all other exceptions
}
Jeśli masz operacje, które muszą być wykonane niezależnie od tego, czy wystąpił błąd lub nie (zadania porządkowe, takie jak zamykanie gniazda lub połączenie z bazą danych) można umieścić je w finally
bloku po obsługi wyjątków:
try {
...
} catch {
...
} finally {
# cleanup operations go here
}
I już znalazłem odpowiedź, ale jest to o wiele bardziej szczegółowe. Twoje zdrowie. – JustAGuy
Dzięki za dokładne wyjaśnienie. Bardzo przydatne. –