Windows PowerShell : Faire d'une commande un outil réutilisable

Vous pouvez reconditionner et réutiliser le fruit de vos efforts avec les commandes et applets de commande Windows PowerShell.

Don Jones

N'importe comment inexpérimentés vous avec Windows PowerShell lorsque vous démarrez travail avec elle, il y a toujours beaucoup de place pour la croissance. Vous pouvez commencer par faire exécuter des commandes simples, progressez vers les commandes plus complexe et finalement reconditionner ces commandes dans quelque chose qui ressemble et se sent presque comme une cmdlet native. Ceux-ci sont appelés des fonctions avancées et sont officieusement connus comme « script cmdlets. »

Envisager une situation où vous pouvez récupérer des informations d'inventaire critique d'un ordinateur. Vous avez besoin de la version de Windows, le numéro de série de BIOS, le service pack version et processeur d'architecture. Vous pouvez obtenir cette information avec ces trois commandes :

Get-WmiObject –class Win32_OperatingSystem –computername SERVER-R2 | Select-Object –property __SERVER,BuildNumber,Caption,ServicePackMajorVersion
Get-WmiObject –class Win32_BIOS –computername SERVER-R2 | Select-Object –property SerialNumber
Get-WmiObject –class Win32_Processor –computername SERVER-R2 | Select-Object –property AddressWidth

Le problème est que ces commandes génèrent des trois ensembles de résultat différent. Vous ne peut pas directement pipe tout ce que sur un unique fichier CSV, par exemple, pour stocker les données de l'inventaire, ou un seul fichier HTML pour afficher l'inventaire comme une page Web. Il est préférable de regrouper les données en une seule commande paramétrée qui pourrait continuer à utiliser un utilisateur moins expérimentés. Vous avez besoin de la commande à :

  • Accepter un ou plusieurs noms d'ordinateur sous forme de chaînes du pipeline, comme dans :
Get-Content names.txt | Get-OSInfo | ConvertTo-HTML | Out-File info.html
  • Accepter un ou plusieurs noms d'ordinateurs sur un paramètre-ComputerName, comme dans :
Get-OSInfo –computername Server-R2,ServerDC4 | Format-Table
  • Accepter du pipeline un ou plus des objets que chacun possède une propriété de Nom_Ordinateur, comme dans :
Get-ADComputer –filter * -searchbase "ou=West,dc=company,dc=com" | Select-Object @{label='computername';expression={_.Name}} | Get-OSInfo | Export-CSV inventory.csv

De cette façon, vous n'aurez pas besoin à vous soucier d'où viennent les noms d'ordinateurs. Vous aussi jamais besoin de se préoccuper de ce type de sortie vous permettant de créer. La coquille gérera que.

En outre, vous devrez avoir un paramètre –logfile qui accepte un chemin et le nom d'un fichier journal. Parce que la commande sera encore utiliser WMI (Windows Management Instrumentation) pour se connecter et d'informations, il est possible que vous ne pourrez pas à atteindre un ou plusieurs ordinateurs. Vous devez toujours que leurs noms soient écrites dans ce fichier journal, vous pouvez ensuite utiliser pour résoudre le problème ou même de réessayer de ces ordinateurs.

Traitant des erreurs

Vous pouvez accomplir ce dernier bit en utilisant le terrasserConstruction de prises au sein de PowerShell. Enroulez simplement de la première requête WMI dans un terrasserBloc catch. Alors spécifier le paramètre de Stop –ErrorAction, il sera capable de capturer toute la commande génère des erreurs. Définissez une variable qui assure le suivi de savoir si une erreur s'est produite, afin que votre script sait s'il faut essayer les deux prochaines requêtes WMI :

continue = True
Try {
  Get-WmiObject –class Win32_BIOS –computername computername –EA Stop
} Catch {
  continue = False
  computername | Out-File –path logfile –append
}

Traitant d'entrée

La partie tricky traite de l'entrée. Vous recevrez d'entrée dans l'une des deux façons — via le pipeline ou via un paramètre. Vous pouvez en fait directement venant d'entrée via le pipeline au paramètre, à l'aide de la cmdlet-style paramètre obligatoire. Voici la structure de base pour cela :

Function Get-OSInfo {
  [CmdletBinding()]
  param(
    [Parameter(Mandatory=True,ValueFromPipeline=True,ValueFromPipelineByPropertyName=True)]
  [string[]]computername,
  [string]logfile 
 )
  BEGIN {}
  PROCESS {}
  END {}
}

Le bloc de processus au sein de la cmdlet est garanti à exécuter au moins une fois, ce qu'il va faire s'il n'y a aucune entrée de pipeline fournie. S'il y a des entrées de pipeline fournie, alors le bloc de processus exécutera une fois pour chaque élément de canalisations. Il place cet élément dans la variable de nom_ordinateur .

C'est là le problème : Si l'entrée est seulement spécifiée via un paramètre, comme dans le deuxième exemple à puces, puis processus seulement exécutera une fois. Le computername contiendra chaque nom de l'ordinateur qui a été donné au paramètre. Vous devez énumérer ou de « déroulement » ces vous-même. Si ces éléments sont acheminés en, alors vous seulement devrez travailler avec un seul élément à la fois. Vous obtiendrez toujours leur dans la variable de nom_ordinateur .

L'astuce consiste à créer une deuxième fonction qui effectue le travail réel. Utilisez la fonction avancée pour accepter ou l'autre type d'entrée et décomposer choses en nom d'un ordinateur à la fois. Appelez ensuite la deuxième fonction « travailleur », avec le nom d'un seul ordinateur à la fois. Voici la structure de base, ce qui irait à l'intérieur du bloc de processus de la fonction principale :

PROCESS {
  if (PSBoundParameters.ContainsKey('computername')) {
    foreach(computer in computername) {
      OSInfoWorker –computername computer –logfile logfile
    }
  } else {
    OSInfoWorker –computername computername –logfile logfile
  }
}

Finition

Avec les principaux obstacles techniques résolus, rendre tous ensemble et ajouter quelques autres détails, tels que le nettoyage des anciens fichiers de log avant d'exécuter la fonction chaque fois (qui est un candidat parfait pour le bloc BEGIN). Le script qui en résulte, composé de deux fonctions, est un peu long. Cependant, très peu d'il est réelle « programmation ». C'est juste des commandes de Windows PowerShell, comme vous exécuterez sur la ligne de commande. Elles sont juste entourées de beaucoup de structure déclarative pour que tout se comportent comme une applet de commande.

La chose ensemble est affichée sur mon site Web à ow.ly/39YcX , avec une soluce vidéo du code final. Il s'agit d'un modèle que vous pouvez réutiliser absolument. La fonction principale est vraiment juste traitant de l'entrée, vous pouvez donc l'utiliser comme c'est presque. Modifier les paramètres pour correspondre à vos besoins spécifiques, et vous voilà prêt à partir. Le travail se fait dans une fonction distincte.

Le mois prochain, je vais vous montrer comment tout cela comme un module de script facile à distribuer du package. Je vous montrerai également comment configurer un emplacement partagé pour les modules de script que tous vos collègues de l'administrateur peuvent utiliser.

Don Jones

Don Jones est un fondateur de concentré de technologie et répond aux questions sur Windows PowerShell et autres technologies à ConcentratedTech.com. Il est également l'auteur de Nexus.Realtimepublishers.com, ce qui en fait plusieurs de ses livres disponibles en éditions électroniques gratuites sur son site web.

 

Obtenez plus

Article ce mois-ci, l'a un compagnon vidéo procédure pas à pas, ainsi que des exemples téléchargeables de code. Obtenir ces extras ici.

Contenu associé