Windows PowerShellInterception des erreurs

Don Jones

Contenu

Définir une interruption
Arrêtez !
C'est tout dans l'étendue
Rompre absence
Pourquoi vous préoccuper ?

Vidéo

Poursuivre son Étude de la création d'un outil d'inventaire puissant dans Windows PowerShell, Don Jones devient son attention à interception.Dans vidéo d'accompagnement ce mois-ci, n'illustre comment vous pouvez incorporer Gestion des erreurs dans vos fonctions de base à Windows PowerShell.

Dans le précédent article de cette colonne, je vous ai montré comment créer un outil d'inventaire plutôt avancée utilisant Windows PowerShell.L'outil que J'AI créé proposé plusieurs options concernant la sortie, grâce à des fonctionnalités intégrées l'environnement et Utilisation de la fonction d'objets.

Un aspect Il est vrai faible de la fonction que J'AI créé est que qu'il ne peut pas traiter normalement toutes les erreurs peuvent, tels que les problèmes de connectivité ou autorisations.Qui est ce que J'AI voulez adresse dans l'article du mois de la colonne de Windows PowerShell, je recherche dans les fonctionnalités de gestion des erreurs offertes par Windows PowerShell.

Définir une interruption

Le mot-clé interruption dans Windows PowerShell définit un gestionnaire d'erreurs.Lorsqu'une exception se produit dans votre script, l'interpréteur de commandes recherche pour voir si un recouvrement a été défini, cela signifie que l'interruption doit apparaître dans votre script avant que les exceptions se produisent.Pour cette démonstration, je vais assembler un script de test que je sais génère un problème de connectivité : je vais utiliser Get-WmiObject pour vous connecter à un nom de l'ordinateur que je sais n'existe sur le réseau.Mon objectif est pour que l'interruption d'erreur écrire le nom de l'ordinateur incorrecte dans un fichier, me donner un fichier de noms d'ordinateur n'a pas fonctionné.Je vais également inclure connexions aux deux ordinateurs qui sont accessibles (je vais utiliser localhost).Vous pouvez voir le script dans la figure 1 .

Figure 1 Ajout de l'interruption

trap {
  write-host "Error connecting to $computer" -fore red
  "$computer" | out-file c:\demo\errors.txt -append 
  continue
}

$computer = "localhost"
get-wmiobject win32_operatingsystem -comp $computer 

$computer = "server2"
get-wmiobject win32_operatingsystem -comp $computer 

$computer = "localhost"
get-wmiobject win32_operatingsystem -comp $computer

Le résultat de ce script, illustré figure 2 , n'est pas exactement ce que je recherche. Notez que le message "Erreur connecting to…" n'a pas afficher. Le fichier Errors.txt n'a pas été créé soit. En d'autres termes, mon interruption n'a pas exécuter du tout. Qu'est-il arrivé ?

fig02.gif

La figure 2 il n'est pas la sortie que je n'a en espérant pour!

Arrêtez !

La clé est de comprendre un message d'erreur shell normal est différent d'une exception. (Il existe erreurs non fin et les erreurs fin. Erreurs fin arrêter l'exécution de pipeline et entraîne une exception). Uniquement les exceptions pouvant être interceptées. Lorsqu'une erreur se produit, l'interpréteur de commandes examine son variable de ErrorActionPreference $ intégré pour voir ce qu'il doit faire. Cette variable par défaut ayant la valeur « continuer », qui signifie que « afficher un message d'erreur et conserver va ». Changer cette variable en « Arrêt » entraîne pour afficher un message d'erreur et générer une exception récupérable. Cela, toutefois, signifie qu'une erreur dans votre script va faire.

Une meilleure technique consiste à avoir uniquement la cmdlet vous pensez que peut provoquer un problème, utilisez le comportement « Stop. Vous pouvez effectuer cette opération en utilisant le paramètre –ErrorAction (ou –EA), un paramètre courant pris en charge par toutes les cmdlets. La version révisée du script est illustrée figure 3 . Il fonctionne uniquement comme prévu, production de la sortie qui se trouve dans la figure 4 .

Utilisation de la figure 3 - ErrorAction

trap {
  write-host "Error connecting to $computer" -fore red
    "$computer" | out-file c:\demo\errors.txt -append 
  continue
}

$computer = "localhost"
get-wmiobject win32_operatingsystem -comp $computer -ea stop

$computer = "server2"
get-wmiobject win32_operatingsystem  -comp $computer -ea stop

$computer = "localhost"
get-wmiobject win32_operatingsystem  -comp $computer -ea stop

La figure 4 J'obtiens des résultats plus utiles lorsque vous utilisez le paramètre –ErrorAction

L'utilisation de continuer à la fin de l'interruption force le shell pour reprendre l'exécution à la ligne de code après celle qui a généré l'exception. L'autre option est d'utiliser le mot clé pause (j'aborderai que dans un instant). Notez également que la variable $ ordinateur, qui est définie dans le script, est encore valide au sein de l'interruption. C'est parce que l'interruption est une étendue enfant du script lui-même, ce qui signifie que l'interruption pouvez voir toutes les variables dans le script (plus d'informations sur cette dans un instant, trop).

C'est tout dans l'étendue

Un aspect particulièrement difficile de récupération d'erreur dans Windows PowerShell est l'utilisation de portée. L'interface elle-même représente la portée globale, qui contient tout ce qui se poursuit dans l'interpréteur de commandes. Lorsque vous exécutez un script, il obtient son propre portée de script. Si vous définissez une fonction, l'intérieur de la fonction est son propre portée privée et ainsi de suite. Cela crée une sorte de type parent/enfant de la hiérarchie.

Lorsqu'une exception se produit, l'interpréteur de commandes recherche un recouvrement dans la portée actuelle. Cela signifie qu'une exception dans une fonction recherchera un recouvrement à cette fonction. Si l'interpréteur de commandes trouve un recouvrement, le shell exécute l'interruption. Si l'interruption se termine par continuer, l'interpréteur de commandes va reprendre l'exécution de la ligne de code qui suit celle qui a provoqué l'exception, restant dans la même étendue. Voici un peu de pseudocode afin d'illustrer cela :

01  Trap {
02    # Log error to a file
03    Continue
04  }
05  Get-WmiObject Win32_Service –comp "Server2" –ea "Stop"
06  Get-Process

Si une exception se produit à la ligne 5, l'interruption de la ligne 1 s'exécute. L'interruption se termine par continuer, donc reprend l'exécution de la ligne 6.

Maintenant examinons ce exemple légèrement différent d'étendue :

01  Trap {
02    # Log error to a file
03    Continue
04  }
05   
06  Function MyFunction {
07    Get-WmiObject Win32_Service –comp "Server2" –ea "Stop"
08    Get-Process
09  }
10   
11  MyFunction
12  Write-Host "Testing!"

Si une erreur se produit sur la ligne 7, l'interpréteur de commandes recherchera un recouvrement dans étendue la fonction. Il n'y en a pas, l'interpréteur de commandes quitte étendue la fonction et recherche d'un recouvrement dans la portée parent. Il y a un recouvrement et ainsi, il s'exécute à la ligne 1. Dans ce cas, continuer est reprises dans la ligne de code dans la même portée suivi de l'exception, c'est la ligne 12, pas de ligne 8. En d'autres termes, l'interpréteur de commandes ne sont pas de nouveau la fonction une fois qu'il est quitté.

Contraste maintenant ce comportement dans cet exemple :

01  Function MyFunction {
02    Trap {
03      # Log error to a file
04      Continue
05    }
06    Get-WmiObject Win32_Service –comp "Server2" –ea "Stop"
07    Get-Process
08  }
09   
10  MyFunction
11  Write-Host "Testing!"

Dans ce cas, l'erreur de la ligne 6 exécutera l'interruption sur la ligne 2, rester dans étendue la fonction. Le mot-clé continuer restera dans cette étendue, reprendre l'exécution de la ligne 7. C'est l'avantage pour y compris un recouvrement dans la portée dans laquelle vous pensez l'erreur, vous restent dans étendue et peuvent reprendre l'exécution qu'il contient. Mais que se passe-t-il si cette méthode ne fonctionne pas dans votre scénario ?

Cmdlet du mois : objet de comparaison

Ceci est un outil utile pour gérer les planifications de configuration. Objet de comparaison, ou son alias diff, est conçu pour comparer deux jeux d'objets à l'autre. Par défaut, il compare chaque propriété de chaque objet et toutes les différences sont sortie par la commande. Ainsi, imaginez que vous avez obtenu un serveur de services configurés exactement comme vous le souhaitez. Exécutez simplement pour créer une planification initiale :

Get-Service | Export-CliXML c:\baseline.xml

Presque n'importe quel objet peut être transmis à exporter-CliXML qui activera les objets dans un fichier XML. Ultérieurement, vous pouvez exécuter la même commande, telles que Get-Service et comparer les résultats à celui enregistrés XML. Voici comment :

Compare-Object (Get-Service) (Import-CliXML 
  c:\baseline.xml) –property name

Ajout du paramètre –property force la comparaison d'uniquement examiner cette propriété, plutôt que l'objet dans son intégralité. Dans ce cas, vous allez obtenir une liste des noms de service qui sont différentes de votre planification initiale, ce qui indique si les services ont été ajoutés ou supprimés depuis que la planification a été créée.

Rompre absence

J'AI mentionné précédemment, le mot-clé saut. la figure 5 illustre un exemple de comment vous pouvez placer le mot-clé saut dans action.

La figure 5 à l'aide du mot clé saut

01  Trap {
02    # Handle the error
03    Continue
04  }
05   
06  Function MyFunction {
07    Trap {
08      # Log error to a file
09      If ($condition) {
10        Continue
11      } Else {
12        Break
13      }
14    }
15    Get-WmiObject Win32_Service –comp "Server2" –ea "Stop"
16    Get-Process
17  }
18   
19  MyFunction
20  Write-Host "Testing!"

Voici un aperçu rapide de la chaîne de l'exécution. Ligne 19 exécute la première, appeler la fonction de la ligne 6. Ligne 15 s'exécute et génère une exception. Cette exception est interceptée de ligne 7 et puis sur ligne 9 l'interruption doit prendre une décision. En supposant que $ condition est True, l'interruption continuera l'exécution de la ligne 16.

Si, toutefois, $ condition est False, l'interruption va rompre. Il quitte la portée actuelle et le transmet l'exception d'origine à l'objet parent. À partir d'affichage l'interpréteur de commandes, qui implique une ligne 19 généré une exception, qui est interceptée par ligne 1. Le mot-clé continuer force le shell pour reprendre la ligne 20.

En réalité, les deux de ces interruptions serait contiennent un peu plus de code pour gérer l'erreur, consigner, etc.. J'ai simplement omis ce code fonctionnel dans cet exemple pour rendre le flux réel plus voir.

Pourquoi vous préoccuper ?

Quand avez-vous besoin d'implémenter l'interception des erreurs ? Uniquement lorsque vous anticipez une erreur peut se produire, et que lorsque vous souhaitez que certains comportement other than un message d'erreur simple, comme une session l'erreur un fichier ou affichant un message d'erreur plus utiles.

J'AI incluent généralement dans les scripts plus complexes afin de traiter les erreurs que J'AI pouvez foresee ne se produise de gestion des erreurs. Ces incluent, mais ne sont pas limités, aux erreurs comme des problèmes de connectivité ou autorisations incorrects.

Interception des erreurs sans aucun doute nécessite un peu plus par l'effort et temps de comprendre. Au cours en tâches plus complexes dans Windows PowerShell, cependant, récupération d'erreur seront également important de l'investissement afin de que vous font un outil plus élaborée et plus professionnel.

Don Jones est le co-auteur de Windows PowerShell: TFM et l'auteur de dizaines d'autres livres D'INFORMATIQUE. Vous pouvez le contacter via son blog à concentratedtech.com.