Windows PowerShell: Trasformare un comando in uno strumento riutilizzabile

I comandi e i cmdlet di Windows PowerShell possono essere rielaborati e riutilizzati.

Don Jones

Non importa come inesperti siete con Windows PowerShell quando prima iniziare a lavorare con esso, c'è sempre spazio per la crescita. Si può iniziare l'esecuzione di semplici comandi, lavorare fino ai comandi più complicate e infine riconfezionare tali comandi in qualcosa che si guarda e si sente quasi come un cmdlet nativo. Questi sono denominati funzioni avanzate e informalmente sono conosciuti come "script cmdlet."

Considerare una situazione in cui è possibile recuperare alcune informazioni critiche di inventario da un computer. È necessario che la versione di Windows, il numero di serie del BIOS, service pack versione e processor architecture. È possibile ottenere tali informazioni con questi tre comandi:

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

Il problema è che questi comandi generano tre set di risultati diversi. È direttamente non pipe tutto ciò che fuori per un singolo file CSV, ad esempio, per memorizzare i dati di inventario, o di un singolo file HTML per visualizzare l'inventario come una pagina Web. È preferibile per incorporare i dati in un unico comando con parametri che ancora potrebbe utilizzare un utente meno esperti. È necessario che il comando:

  • Accettare uno o più nomi di computer come stringhe dalla pipeline, come in:
Get-Content names.txt | Get-OSInfo | ConvertTo-HTML | Out-File info.html
  • Accettare uno o più nomi di computer su un parametro – ComputerName, come in:
Get-OSInfo –computername Server-R2,ServerDC4 | Format-Table
  • Accettare dalla pipeline di uno o più oggetti che ognuno ha una proprietà computername, come in:
Get-ADComputer –filter * -searchbase "ou=West,dc=company,dc=com" | Select-Object @{label='computername';expression={_.Name}} | Get-OSInfo | Export-CSV inventory.csv

In questo modo, non è necessario preoccuparsi di dove i nomi dei computer sono provenienti da. Inoltre mai bisogno di preoccuparsi di ciò che tipo di output si verrà creata. La shell gestirà che.

Inoltre, si dispone di un parametro Microsoft.CRM.deploymentconfigtool.exe, che accetta un percorso e il nome di un file di log. Perché il comando sarà ancora essere utilizzando Strumentazione gestione Windows (WMI, Windows Management Instrumentation) per connettersi e ricercare informazioni, c'è la possibilità che non sarà in grado di raggiungere uno o più computer. Dovete ancora i loro nomi scritti in file di log, che è quindi possibile utilizzare per risolvere il problema o addirittura per ritentare tali computer.

Trattare con errori

È possibile eseguire tale ultimo bit utilizzando il costrutto Try…CATCH nidificato all'interno di PowerShell. Semplicemente avvolgere la prima query WMI in Try…Blocco catch. Quindi specificare il parametro di Stop – ErrorAction in modo che sarà in grado di rilevare eventuali errori che il comando genera. Impostare una variabile che consente di determinare se si è verificato un errore, in modo che lo script sarà sapere se per provare le prossime due query WMI:

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

Trattare con Input

La parte difficile è trattare con l'ingresso. Riceverai un ingresso in uno dei due modi — tramite la pipeline o un parametro. Si può effettivamente diretto input provenienti attraverso la pipeline al parametro, utilizzando il cmdlet-stile associazione di parametro. Qui è la struttura di base per questo:

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

Il blocco del processo all'interno del cmdlet è garantito da eseguire almeno una volta, che farà se non vi è alcuna immissione in pipeline fornita. Se non esiste una pipeline di input fornito, quindi il blocco del processo eseguirà una volta per ogni elemento reindirizzato in. Tale elemento metterà nella variabile NomeComputer.

Qui sta il problema: Se l'input viene specificato solo tramite un parametro, come nel secondo esempio puntato, quindi processo viene eseguito solo una volta. NomeComputer conterrà ogni nome del computer che è stato dato al parametro. Si avrebbe enumerare o "rilassarsi" quei voi stessi. Se tali elementi vengono reindirizzati, quindi ti hanno solo a lavorare con un solo elemento alla volta. Li avrai ancora nella variabile NomeComputer.

Il trucco è quello di creare una seconda funzione che fa il lavoro effettivo. Utilizzare la funzione avanzata di accettare ogni tipo di input e rompere le cose in nome di un computer alla volta. Quindi chiamare la funzione di "lavoratore" seconda con il nome di un unico computer per volta. Qui è la struttura di base, che andrebbe all'interno del blocco del processo della funzione principale:

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

Ultimi ritocchi

Con i principali ostacoli tecnici risolti, portare tutti insieme e aggiungere alcuni altri dettagli, come la pulizia dei vecchi file di registro prima di eseguire la funzione ogni volta (che è un candidato ideale per il blocco BEGIN). Lo script risultante, costituito da due funzioni, è un po' lungo. Tuttavia, molto poco di esso è effettiva "programmazione". La maggior parte di esso è solo i comandi di Windows PowerShell, come sarebbe eseguita sulla riga di comando. Hanno appena sei circondati da un sacco di struttura dichiarativa per renderlo tutti si comportano come un cmdlet.

L'intera cosa è pubblicato sul mio sito Web a ow.ly/39YcX , con un video progressione del codice finale. Questo è un modello che è assolutamente possibile riutilizzare. La funzione primaria è davvero solo occupando l'input, così potete usarlo quasi come è. Modificare i parametri per le vostre esigenze specifiche, e stai per andare bene. Il lavoro effettivo è stato fatto in una funzione distinta.

Il mese prossimo, ti mostrerò come fare un pacchetto tutto questo come un modulo facile-a-distribuire script. Anche mostrerò come impostare un percorso condiviso per i moduli di script che tutti i colleghi di amministratore può utilizzare.

Don Jones

Don Jones è il fondatore di concentrato di tecnologia e risposte domande su Windows PowerShell e altre tecnologie a ConcentratedTech.com. Egli è anche un autore di Nexus.Realtimepublishers.com, che molti dei suoi libri rende disponibili come liberi edizioni elettroniche attraverso il suo sito web.

 

Ottieni di più

Articolo di questo mese ha un compagno walkthrough video, così come codice di esempio scaricabile. Ottenere questi extra qui.

Contenuto correlato