Windows PowerShell Creación de una herramienta de inventario mejor

Don Jones

Contenido

Objetos son siempre iguales
Salida flexible
Entrada flexible
¿Qué ocurre con errores?
Hacer esto realmente útiles

En la entrega anterior de esta columna, he creado una función que se pudo recuperar la información de inventario service pack desde varios equipos remotos. Aunque esto es una herramienta muy práctica que puede ser muy útil, también estaba relacionado con el proceso que utilizado para desarrollar la herramienta. En esta entrega, quiero demostrar el proceso que se usa por lo que será mejor equipado crear sus propias funciones.

La función que he creado en la entrega anterior es similar a ésta:

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

Y aquí es cómo se puede utilizar:

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

Esto funciona bien, si el archivo de texto incluye uno nombre de equipo por línea.

Un punto débil particular de esta función es que es limitado a devolver datos de una clase WMI (Instrumental de administración de Windows).Por lo tanto ¿qué ocurre si también deseo devolver el número de serie del BIOS?

Objetos son siempre iguales

El problema es que mi función es recuperar la clase Win32_OperatingSystem de WMI y simplemente producir ese objeto.La clase Win32_OperatingSystem, como todos los objetos, es fija en los datos contiene, no incluyen un número de serie del BIOS y no puede.Siempre que simplemente me producir objetos Win32_OperatingSystem, el resultado nunca puede incluir un número de serie.

Independientemente de cuánto rummage alrededor en WMI, no encontrará una clase de objeto único que incluye números de serie del BIOS y información del paquete de servicio.Como resultado, mi función no puede simplemente salida de una clase WMI.En su lugar, necesito que la salida de un objeto personalizado que componen sobre la marcha, uno que contiene todos los datos se necesita.

Para crear un nuevo objeto en blanco no tengan propiedades, sólo ejecute esto:

$obj = New-Object PSObject

El objeto nuevo se almacena en la variable obj $, y pueden agregar los datos desee a ella. Una vez que haya agregado todos los datos, a continuación, será el resultado de la función.

Dentro de la función, ha recuperar la información de Win32_OperatingSystem y se almacena en la variable wmi $. Usar esa información es tan sencillo como hacer referencia a las propiedades de wmi $. Por ejemplo, para obtener la propiedad BuildNumber, utilizaría esta:

$wmi.BuildNumber

Para agregar una propiedad en el objeto personalizado, tener que canalizar el objeto (que se encuentra en la variable obj $) a miembros de agregar. SE sabe Add-miembro qué tipo de propiedad deseo agregar (siempre NoteProperty), el nombre de la propiedad desea agregar y el valor desea la propiedad para que tenga, así:

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

Puede hacer esto para el nombre del equipo y servicio versión pack así:

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

Ajuste que arriba proporciona una nueva función (consulte la figura 1 ). Observe que ha cambiado la línea de salida de escritura para el objeto personalizado, en vez de objeto wmi original $ de salida.

Figura 1 objeto personalizado

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
  }
}

Ahora es necesario obtener ese número de serie del BIOS. Algunas búsquedas, activa la clase Win32_BIOS, que tiene una propiedad Serial­Number ( figura 2 muestra una parte de la página de documentación en línea). Para que sólo tenga que consultar la clase Win32_BIOS, agregar la propiedad Serial­Number en el objeto personalizado y me realiza. Puede ver la función revisada en la figura 3 .

fig02.gif

La Figura 2 Win32_BIOS clase documentación página (haga clic en la imagen de una vista más grande)

Propiedad de número de serie con la figura 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
  }
}

Salida flexible

Mediante un objeto personalizado para la salida, he creado una variedad de usos posibles de esta función. Por ejemplo, para incluir sólo los equipos de Windows Server 2008, puede utilizar esta:

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

O bien, para crear un archivo de código HTML que enumera todos los equipos de Windows Vista que no tengan instalado el Service Pack 1, puede utilizar esta:

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

Las posibilidades son infinitas, XML, CSV, tablas, listas, HTML, ordenadas, filtrado, agrupado y así sucesivamente. Los cmdlets integrados en Windows PowerShell están diseñados para trabajar con objetos. Al crear objetos de la salida, puede aprovechar las ventajas de todo lo que Windows PowerShell es capaz de hacerlo, con ningún trabajo adicional.

Entrada flexible

Por desgracia, mi función no es tan flexible en términos de entrada. Parcialmente es una limitación de cómo las funciones están diseñadas en la versión 1 de Windows PowerShell, versión 2 se presentan los cmdlets de secuencia de comandos, que ofrecen flexibilidad mucho más.

Mi función espera la canalización que objetos simple cadena de entrada. La función no funciona si reemplazar el comando Get-Content, por ejemplo, un cmdlet para recuperar todos los nombres de los equipos de Active Directory, como éste:

Get-QADComputer | Get-SPInventory

En este caso, el comando Get-QADComputer (parte de un conjunto libre de los cmdlets de administración de Active Directory que se puede obtener en quest.com/powershell) se devuelve un objeto que tiene una propiedad de nombre, en lugar devolver objetos de cadena simple. Para que ese comando trabajo, tendría que ajustar la función, que se muestra en la figura 4 ; es importante para que tenga en cuenta que los cambios aparecen resaltados en rojo.

La figura 4 el producto 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
  }
}

En lugar de pasar el objeto canalización todo en el parámetro –computerName, mi función ahora está actuando en nombre de propiedad el objeto de canalización. Este cambio menor pena bastante en términos de flexibilidad, mediante el uso de Get-QADComputer, estoy puede limitar la entrada a equipos en una unidad organizativa específica, por ejemplo, o para que sólo los equipos que son que coinciden con otros criterios de según los atributos de Active Directory.

¿Qué ocurre con errores?

Inevitablemente, esta función, finalmente, llegará a través de un equipo que no puede conectar a, no tiene permisos para conectarse a, o así sucesivamente. La función, que actualmente se escribe, mostrará un mensaje de error en texto rojo en la ventana de consola de Windows PowerShell y continúe en el siguiente equipo.

Que, por supuesto, es posible que es justo lo que desea que realice. O puede que prefiera la función para suprimir los mensajes de error. Esto es fácil de hacer simplemente agregando la una línea al principio del bloque de secuencias de comandos de la función PROCESS:

$ErrorActionPreference = "SilentlyContinue"

A continuación, nuevo, quizás desee adoptar un enfoque más complejo y crear un registro de errores que enumera los nombres de los equipos que no estaban accesibles. Windows PowerShell puede hacer, pero tendrá que esperar hasta el próximo mes para ver cómo hacerlo.

Cmdlet del mes: exportar de alias Y alias de importación

Ésta es una manera excelente para compartir alias personalizados que haya creado o para cargar fácilmente sus alias personalizados cada vez que inicie el shell. Después de crear todos los alias que desee, exportarlos a un archivo, como éste:

Exportación de alias c:\aliases.xml

A continuación, para cargar los alias de nuevo en el shell, ejecute este comando:

Importación de alias c:\aliases.xml

Puede colocar ese segundo comando en la secuencia de comandos perfil de Windows PowerShell que se ejecute cada vez que inicia el shell. Además, puede colocar el archivo en un recurso compartido de red para tener fácilmente disponibles para los otros administradores que trabaja.

Hacer esto realmente útiles

Hasta ahora, que es posible que haya ha escribiendo esta función en un archivo. ps1 y ejecutar la secuencia de comandos. Todo bien y buena, pero tiene unos pocos problemas de uso. Un problema es que siempre que desee utilizar la función que tendría que abrir ese archivo de secuencia de comandos, modifique la línea que llama a la función (para agregar los resultados, ordenar o otros comandos que necesita en ese momento), guarde la secuencia de comandos y ejecutarlo. Sería mucho más fácil si la propia función disponible hacia la derecha dentro ventana de consola del shell en la, casi como un cmdlet.

Hay dos opciones para ir sobre cómo hacerlo. El primero es simplemente copie la función en una secuencia de comandos de perfil de Windows PowerShell, uno de los cuatro archivos de secuencias de comandos que el shell se ejecutará automáticamente (si existen) cada vez que se inicia. La Guía de inicio rápido que se instala con Windows PowerShell se enumeran las cuatro ubicaciones.

Suele utilizar el archivo que se denomina profile.ps1, que tiene que se encuentra en la carpeta denominada Windows­PowerShell (sin espacios) dentro de la carpeta de documentos (o documentos en equipos con Windows XP y Windows Server 2003). Una vez que la función está en su perfil, tendrá se disponibles directamente desde el símbolo del sistema siempre está en el shell.

La segunda opción es para que incluya la función, sólo la función, con ningún otro código, en un origen de secuencia de comandos y punto que secuencias de comandos en el shell. Lo que normalmente ocurre al ejecutar una secuencia de comandos es que Windows PowerShell se crea un nuevo ámbito de la secuencia de comandos. Todo lo que pasa en la secuencia de comandos tiene lugar dentro de ese ámbito, tales como la definición de funciones. Cuando la secuencia de comandos termina de ejecutarse, se descarta el ámbito y todo lo que fue en dentro de ese ámbito se pierde.

Como consecuencia de esto, recuerde que si tiene un archivo de secuencia de comandos que contiene sólo la función de Get-SP­Inventory, que ejecutan que secuencia de comandos se crean un ámbito nuevo, definir la función y descartar el ámbito, y, a continuación, se desaparecen la función. Obviamente, no es muy útil para usted.

Punto de suministro, por otro lado, ejecuta una secuencia de comandos sin crear un nuevo ámbito. Si ha coloca Get-SPInventory en un archivo denominado MyFunction.ps1, puede dot origen, como éste:

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

Tenga en cuenta el período única, seguido por un espacio, que precede a la de ruta de acceso y nombre de archivo secuencia de comandos. Que indica el shell para ejecutar la secuencia de comandos en el ámbito actual, lo que significa que todo lo que sucede en la secuencia de comandos cumplir alrededor después de que la secuencia de comandos finalice la ejecución. El resultado es que la secuencia de comandos get-SPInventory ya está definido en el shell y puede utilizarlo directamente desde la línea de comandos, casi como si fuera un cmdlet.

Don Jones es cofundador de tecnología concentró y autor de numerosos libros de INFORMÁTICA. Leer sus sugerencias de Windows PowerShell semanales o póngase en contacto con él en ConcentratedTech.com.