Windows PowerShell Création d'un outil d'inventaire plu

Don Jones

Contenu

Objets sont toujours identique
Sortie flexible
Entrée flexible
Qu'en est-il des erreurs ?
Rendre cette Really utiles

Dans le précédent article de cette chronique, J'AI créé une fonction qui pourrait extraient des informations sur le stock service pack de plusieurs ordinateurs distants. Bien que ce soit un outil très pratique qui peut être très pratique, j'ai également préoccuper du processus que J'AI utilisé pour développer l'outil. Dans cet article, je souhaite illustrer le processus de qu'utilisation afin vous soit mieux équipés pour créer vos propres fonctions.

La fonction que J'AI créé dans l'article précédent se présente comme suit :

Function Get-SPInventory {
  PROCESS {
    $wmi = Get-WmiObject Win32_OperatingSystem  
      –comp $_ | 
    Select CSName,BuildNumber,
      ServicePackMajorVersion
    Write-Output $wmi
  }
}

Et ici est comment vous pouvez l'utiliser :

Get-Content c:\computernames.txt | 
Get-SPInventory

Cela fonctionne bien, si le fichier texte inclut une nom de l'ordinateur par ligne.

Une faiblesse particulier de cette fonction est qu'il est limité à renvoyer des données d'une classe WMI (Windows Management Instrumentation) unique.Ainsi, que se passe-t-il si je également souhaite renvoyer le numéro de série du BIOS ?

Objets sont toujours identique

Le problème est que ma fonction récupération de la classe Win32_OperatingSystem à partir de WMI et il vous suffit de générer cet objet.La classe Win32_OperatingSystem, comme tous les objets, est résolue dans les données qu'il contient, il n'est pas inclure un numéro de série du BIOS et ne pouvez.Tant que je suis éditant simplement objets Win32_OperatingSystem, mon résultat pouvez jamais inclure un numéro de série.

Quel que soit la quantité vous rummage autour de WMI, vous trouverez pas une classe d'objet unique qui inclut les numéros de série du BIOS et informations sur le service pack.Par conséquent, ma fonction ne peut pas exporter simplement une classe WMI.Avez au lieu de cela, J'AI besoin d'un objet personnalisé qui je composent à la volée de sortie, qui contient toutes les données J'AI besoin.

Pour créer un nouvel objet vide à aucune des propriétés, J'AI simplement exécuter cette :

$obj = New-Object PSObject

Le nouvel objet est stocké dans la variable obj $, et je pouvez ajouter que données souhaitée à il. Une fois que J'AI avez ajouté toutes mes données, il devient ensuite le résultat de ma fonction.

Dans ma fonction, j'ai extrait les informations Win32_OperatingSystem et il stocké dans le wmi $ variable. Utiliser ces informations est aussi simple que la référence à des propriétés de wmi $. Par exemple, pour obtenir la propriété BuildNumber, J'AI utiliseriez cette :

$wmi.BuildNumber

Pour ajouter une propriété à mon objet personnalisé, je dois transférer l'objet (qui est la variable obj $) membre de l'ajouter. Savoir Add-membre quel type de propriété que je souhaite ajouter (toujours NoteProperty), le nom de la propriété je souhaite ajouter et la valeur souhaitée pour la propriété ait, comme suit :

$obj | Add-Member NoteProperty BuildNumber 
($wmi.BuildNumber)

Je peux faire ceci pour le nom de système de l'ordinateur et service pack version ainsi :

$obj | Add-Member NotePropertyCSName 
  ($wmi.CSName)
$obj | Add-Member NotePropertySPVersion 
  ($wmi.ServicePackMajorVersion)

Habillage que des rendements une nouvelle fonction (voir figure 1 ). Notez que J'AI avez modifié la ligne Write-production pour copier l'objet personnalisé plutôt qu'à l'objet wmi $ d'origine.

Objet personnalisé 1 A figure

Function Get-SPInventory {
  PROCESS {
    $wmi = Get-WmiObject Win32_       OperatingSystem –comp $_ | 
       Select CSName,BuildNumber,ServicePack         MajorVersion
    $obj = New-Object PSObject
    $obj | Add-Member NoteProperty 
      BuildNumber ($wmi.BuildNumber)
    $obj | Add-Member NoteProperty CSName      ($wmi.CSName) 
    $obj | Add-Member NoteProperty SPVersion 
      ($wmi.ServicePackMajorVersion)
    Write-Output $obj
  }
}

Je dois maintenant récupérer ce numéro de série du BIOS. Une recherche active jusqu'à la classe Win32_BIOS, qui possède une propriété Serial­Number ( figure 2 affiche une partie de la page de documentation en ligne). Afin de je dois simplement interroger la classe Win32_BIOS, ajoutez la propriété Serial­Number à mon objet personnalisé, puis ai j'fait. Vous pouvez voir la fonction révisée à la figure 3 .

fig02.gif

La figure 2 Win32_BIOS classe page documentation (cliquez sur l'image pour l'agrandir)

Propriété de numéro de série À la figure 3

Function Get-SPInventory {
  PROCESS {
    $wmi = Get-WmiObject Win32_      OperatingSystem –comp $_ |    
      Select CSName,BuildNumber,ServicePack        MajorVersion
    $obj = New-Object PSObject
    $obj | Add-Member NoteProperty 
      BuildNumber ($wmi.BuildNumber)
    $obj | Add-Member NoteProperty CSName      ($wmi.CSName)
    $obj | Add-Member NoteProperty SPVersion 
      ($wmi.ServicePackMajorVersion)

    $wmi = Get-WmiObject Win32_BIOS –comp $_ | 
      Select SerialNumber
    $obj | Add-Member NoteProperty BIOSSerial 
      ($wmi.SerialNumber)
    Write-Output $obj
  }
}

Sortie flexible

En utilisant un objet personnalisé pour la sortie, j'ai créé une variété d'utilise potentiel pour cette fonction. Par exemple, pour inclure uniquement les ordinateurs Windows Server 2008, je peux utiliser ceci :

Gc c:\computernames.txt | Get-SPInventory | 
Where { $_.BuildNumber –eq 6001 }

Ou, pour créer un fichier HTML répertoriant tous les ordinateurs Windows Vista qui n'ont pas Service Pack 1 installé, je pouvez utiliser ceci :

Gc c:\computernames.txt | Get-SPInventory | 
Where { $_.BuildNumber –eq 6000 } | 
ConvertTo-HTML | Out-File c:\VistaInventory.html

Les possibilités sont infinies, XML, CSV, tableaux, listes, HTML, triés, filtré, groupés et ainsi de suite. Les cmdlets intégrées dans Windows PowerShell sont conçus pour travailler avec des objets. En créant des objets de la sortie, vous pouvez tirer parti de tout ce que Windows PowerShell est capable de ceci, aucun travail supplémentaire !

Entrée flexible

Malheureusement, ma fonction n'est pas aussi flexible en termes d'entrée. Il s'agit partiellement d'une limitation de la façon dont les fonctions sont conçues dans la version 1 de Windows PowerShell, version 2 présente les cmdlets de script, qui offrent beaucoup plus de flexibilité.

Ma fonction attend son pipeline à objets simple chaîne d'entrée. La fonction ne fonctionne si je devais pour remplacer la commande Get-Content, par exemple, une cmdlet pour récupérer tous les noms d'ordinateur dans Active Directory, à ceci :

Get-QADComputer | Get-SPInventory

Dans ce cas, la commande Get-QADComputer (partie d'un jeu de cmdlets de gestion Active Directory que vous pouvez obtenir à quest.com/powershell libre) est renvoyant un objet qui possède une propriété nom, plutôt que renvoyant des objets chaîne simple. Pour rendre cette commande fonctionne, je devez devez modifier la fonction, illustrée figure 4 ; il est important pour vous de noter que les modifications sont en rouge.

La figure 4 le produit final

Function Get-SPInventory {
  PROCESS {
    $wmi = Get-WmiObject Win32_OperatingSystem –<span class="clsRed" xmlns="http://www.w3.org/1999/xhtml">comp 
    $_.Name</span> | Select 
      CSName,BuildNumber,
        ServicePackMajorVersion
    $obj = New-Object PSObject
    $obj | Add-Member NoteProperty 
      BuildNumber ($wmi.BuildNumber)
    $obj | Add-Member NoteProperty CSName 
      ($wmi.CSName)
    $obj | Add-Member NoteProperty SPVersion  
      ($wmi.ServicePackMajorVersion)

    $wmi = Get-WmiObject Win32_BIOS –comp <span class="clsRed" xmlns="http://www.w3.org/1999/xhtml">$_.Name |</span> 
      Select SerialNumber
    $obj | Add-Member NoteProperty BIOSSerial 
      ($wmi.SerialNumber)
    Write-Output $obj
  }
}

Plutôt que de passez l'objet pipeline ensemble au paramètre –computerName, ma fonction opère maintenant sur Nom de propriété l'objet pipeline. Cette modification mineure est très utile en termes de flexibilité, en utilisant Get-QADComputer, je peux limiter mon entrée aux ordinateurs dans une unité d'organisation spécifique, par exemple, ou sur les ordinateurs des correspondent autres critères basés sur des attributs Active Directory.

Qu'en est-il des erreurs ?

Inévitablement, cette fonction est fourni par la suite sur un ordinateur sur lequel il ne peut pas se connecter à, il n'est pas avoir l'autorisation pour vous connecter à, ou ainsi de suite. La fonction, telles qu'elles sont écrites actuellement, affiche un message d'erreur en rouge dans la fenêtre de console Windows PowerShell et puis passez à l'ordinateur suivant.

Qui, bien sûr, peut-être simplement que souhaité faire. Ou vous pouvez préférez la fonction pour supprimer les ces messages d'erreur. Il est facile à faire tout simplement ajouter cette ligne au début du bloc de script PROCESS la fonction :

$ErrorActionPreference = "SilentlyContinue"

Puis nouveau, vous souhaiterez peut-être adopter une approche plus complexe et créer un journal d'erreurs qui répertorie les noms des ordinateurs qui n'étaient pas accessibles. Windows PowerShell pour ce faire, mais vous vous avez à attendre que le mois suivant pour voir comment cela !

Cmdlet du mois : alias de l'exportation et Importation-alias

Voici un moyen idéal pour partager des alias personnalisés que vous avez créé ou pour facilement charger votre alias personnalisés à chaque démarrage de l'interpréteur de commandes. Après avoir créé tous les alias souhaité, les exporter dans un fichier, comme suit :

Exportation-alias c:\aliases.xml

Ensuite, pour charger les alias dans l'interpréteur de commandes, exécutez cette commande :

Importer-alias c:\aliases.xml

Vous pouvez placer cette deuxième commande dans votre script profil Windows PowerShell pour l'exécuter chaque fois que l'environnement démarre. En outre, vous pouvez placer le fichier sur un partage réseau afin d'avoir facilement disponibles pour les autres administrateurs vous travaillez avec.

Rendre cette Really utiles

Jusqu'ici, vous pouvez avoir été tapez cette fonction dans un fichier. ps1 et exécuter le script. C'est tout bien et bien, mais il comporte quelques problèmes de facilité d'utilisation. Un problème est que chaque fois que vous souhaitez utiliser la fonction que vous devrez peut-être ouvrir ce fichier de script, modifiez la ligne qui appelle la fonction (pour ajouter le résultat, le tri ou autres commandes que nécessaires à ce moment), enregistrez le script et exécutez-le. Il serait beaucoup plus facile si la fonction elle-même était disponible directement dans la fenêtre de console l'interpréteur de commandes, pratiquement comme une cmdlet.

Il existe deux options pour passer sur cette opération. La première est de copier simplement la fonction dans un script de profil Windows PowerShell, un des quatre fichiers de script qui l'interpréteur de commandes s'exécutent automatiquement (s'ils existent) chaque fois qu'il démarre. Le Guide de démarrage rapide qui est installé avec Windows PowerShell répertorie les quatre emplacements.

Je généralement utiliser le fichier nommé profile.ps1, qui doit se trouver dans le dossier nommé Windows­PowerShell (espaces non compris) dans votre dossier documents (ou Mes documents sur les ordinateurs Windows XP et Windows Server 2003). Une fois la fonction dans votre profil, il vous accessibles directement à partir de l'invite de commande chaque fois que vous êtes dans l'interpréteur de commandes.

La deuxième option est d'inclure la fonction, uniquement la fonction, avec aucun autre code, dans une source script et de point de script dans l'interpréteur de commandes. Ce qui se produit généralement lorsque vous exécutez un script est que Windows PowerShell crée une nouvelle étendue pour le script. Tout ce qui se poursuit dans le script s'effectue dans cette étendue, telles que la définition de fonctions. Lorsque le script exécution est terminée, la portée est ignorée et tout ce qui s'est passé sur dans cette étendue est perdu.

En raison de cela, rappelez-vous que si vous avez un fichier de script contenant uniquement la fonction Get-SP­Inventory, que script va créer une nouvelle étendue, définir la fonction et ignorer l'étendue, et ensuite la fonction disparaissent. Bien entendu, qui n'est pas très utile pour vous.

Point approvisionnement, d'autre part, s'exécute un script sans créer une nouvelle étendue. Si j'ai mis Get-SPInventory dans un fichier nommé MyFunction.ps1, J'AI pouvez point source comme suit :

PS C:\> . c:\functions\myfunction

Notez la période Antilope, suivie par un espace qui précède le chemin d'accès et le nom le script de. Qui indique l'environnement pour exécuter le script dans la portée actuelle, ce qui signifie que tout ce qui se produit dans le script coller autour d'une fois le script terminée. Le résultat est que le script Get-SPInventory est maintenant défini dans l'interpréteur de commandes et vous pouvez l'utiliser directement à partir de la ligne de commande, pratiquement comme s'il était une cmdlet.

Don Jones est co-fondateur de technologie concentrés et auteur de nombreux livres D'INFORMATIQUE. Lire ses conseils Windows PowerShell hebdomadaires ou contactez-le à ConcentratedTech.com.