web-dev-qa-db-fra.com

Capture du message d'exception PLEIN

Considérer:

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

Cela lève l'exception suivante:

Enter image description here

Comment puis-je l'attraper complètement ou au moins filtrer "Une ressource portant le même nom existe déjà."?

En utilisant $_.Exception.GetType().FullName

System.Net.WebException

et $_.Exception.Message donne

Le serveur distant a renvoyé une erreur: (400) requête incorrecte.

46
JustAGuy

Les erreurs et les exceptions dans PowerShell sont des objets structurés. Le message d'erreur que vous voyez imprimé sur la console est en fait un message formaté contenant des informations provenant de plusieurs éléments de l'objet error/exception. Vous pouvez (re) construire vous-même comme ceci:

$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

Si vous souhaitez simplement que le message d'erreur soit affiché dans votre bloc catch, vous pouvez simplement faire écho à la variable d'objet en cours (qui contient l'erreur à cet endroit):

try {
  ...
} catch {
  $_
}

Si vous avez besoin d'une sortie en couleur, utilisez Write-Host avec une chaîne formatée comme décrit ci-dessus:

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

Cela dit, vous ne voulez généralement pas afficher le message d'erreur tel quel dans un gestionnaire d'exceptions (sinon, le -ErrorAction Stop ne servirait à rien). Les objets d'erreur/exception structurés vous fournissent des informations supplémentaires que vous pouvez utiliser pour un meilleur contrôle des erreurs. Par exemple, vous avez $_.Exception.HResult avec le numéro d'erreur actuel. $_.ScriptStackTrace et $_.Exception.StackTrace, vous pouvez donc afficher les traces de pile lors du débogage. $_.Exception.InnerException vous donne accès aux exceptions imbriquées contenant souvent des informations supplémentaires sur l'erreur (les erreurs de niveau supérieur PowerShell peuvent être quelque peu génériques). Vous pouvez dérouler ces exceptions imbriquées avec quelque chose comme ceci:

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

Dans votre cas, les informations que vous souhaitez extraire semblent se trouver dans $_.ErrorDetails.Message. Je ne sais pas très bien si vous avez un objet ou une chaîne JSON ici, mais vous devriez pouvoir obtenir des informations sur les types et les valeurs des membres de $_.ErrorDetails en exécutant

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

Si $_.ErrorDetails.Message est un objet, vous devriez pouvoir obtenir la chaîne de message comme ceci:

$_.ErrorDetails.Message.message

sinon, vous devez d'abord convertir la chaîne JSON en objet:

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

Selon le type d'erreur que vous gérez, les exceptions de types particuliers peuvent également inclure des informations plus spécifiques sur le problème rencontré. Dans votre cas, par exemple, vous avez un WebException qui, en plus du message d'erreur ($_.Exception.Message), contient la réponse réelle du serveur:

PS C: \> $ e.Exception | Get-membre
 
 TypeName: System.Net.WebException 
 
 Nom MemberType Définition 
 ---- ---------- - --------- 
 Méthode Equals bool Equals (Objets obj), bool _Exception.E ... 
 Méthode GetBaseException System.Exception Get.BaseException (), System.Excep. .. 
 Méthode GetHashCode int GetHashCode (), int _Exception.GetHashCode () 
 Méthode GetObjectData void GetObjectData (System.Runtime.Serialization.S ... 
 GetType Type de méthode GetType ( ), tapez _Exception.GetType () 
 ToString Méthode string ToString (), string _Exception.ToString () 
 Propriété de données System.Collections.IDictionary Données {get;} 
 Propriété HelpLink, propriété string HelpLink {get; set;} 
 Propriété HResult int HResult {get;} 
 InnerException Propriété System.Exception InnerException {get;} 
 Message Propriété string Message {get;} 
Réponse, propriété System.Net.WebResponse Response {get;}
 Propriété source string Source {get; set;} 
 StackTrace Propriété string StackTrace {get;} 
 Status Propriété System.Net.WebExceptionStatus Status {get;} 
 Propriété TargetSite System.Reflection.MethodBase TargetSite {get;}

qui vous fournit des informations comme celle-ci:

PS C: \> $ e.Exception.Response
 
 IsMutuallyAuthenticated: False 
 Cookies: {} 
 En-têtes: {Keep-Alive, Connexion, Longueur du contenu, Contenu-T ...} 
 SupportsHeaders: True 
 ContentLength: 198 
 ContentEncoding: 
 ContentType: text/html; charset = iso-8859-1 
 CharacterSet: iso-8859-1 
 Serveur: Apache/2.4.10 
 Dernière modification: 17.07.2016 14:39:29 
 StatusCode: NotFound 
 StatusDescription: non trouvé 
 ProtocolVersion: 1.1 
 ResponseUri: http://www.example.com/
Method: POST 
 IsFromCache: False

Étant donné que toutes les exceptions ne possèdent pas exactement le même ensemble de propriétés, vous pouvez utiliser des gestionnaires spécifiques pour des exceptions particulières:

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

Si des opérations doivent être effectuées, qu'une erreur soit survenue ou non (tâches de nettoyage telles que la fermeture d'un socket ou une connexion à une base de données), vous pouvez les placer dans un bloc finally après la gestion des exceptions:

try {
  ...
} catch {
  ...
} finally {
  # cleanup operations go here
}
76
Ansgar Wiechers

Je l'ai trouvé!

Imprimez simplement $Error[0] pour le dernier message d'erreur.

10
JustAGuy

Vous pouvez ajouter:

-ErrorVariable errvar

Et puis regardez dans $errvar.

5
Tim Ker

Ce qui suit a bien fonctionné pour moi

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

write-Host $string_err

Le résultat de ceci est le suivant en tant que chaîne au lieu d'un objet 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
3
Tareq Saif

Je reviens sans cesse à ces questions pour essayer de déterminer où se trouvent exactement les données qui m'intéressent dans ce qui est vraiment une structure monolithique ErrorRecord. Presque toutes les réponses donnent des instructions fragmentaires sur la manière d'extraire certaines données.

Mais j’ai trouvé extrêmement utile de vider tout l’objet avec ConvertTo-Json afin de pouvoir visualiser visuellement LITTÉRALEMENT TOUT dans une mise en page compréhensible.

    try {
        Invoke-WebRequest...
    }
    catch {
        Write-Host ($_ | ConvertTo-Json)
    }

Utilisez le paramètre ConvertTo-Json de -Depth pour développer des valeurs plus profondes, mais faites extrêmement attention en dépassant le rayon par défaut de 2: P.

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

1
mmseng