Recopilación de la información
Soy un gran fan de la programación modular. Gran, gran fan. Con eso en mente, tiendo a escribir funciones que recopilan la información que quiero incluir en mi informe, y normalmente haré una función por sección principal de mi informe. Verá dentro de poco cómo es eso de beneficioso. Escribiendo cada función individualmente, hago más fácil de usar esa misma información en otras tareas, y hago más fácil depurar cada una. El truco consiste en que cada salida de función sea un solo tipo de objeto que combine toda la información de esa sección para el informe. He creado cinco funciones, que he pegado en un solo archivo de script. Le mostraré cada una de esas funciones una a la vez, con un breve comentario. Aquí va la primera:
1 function Get-InfoOS {
2 [CmdletBinding()]
3 param(
4 [Parameter(Mandatory=$True)][string]$ComputerName
5 )
6 $os = Get-WmiObject -class Win32_OperatingSystem -Com\
7 puterName $ComputerName
8 $props = @{'OSVersion'=$os.version;
9 'SPVersion'=$os.servicepackmajorversion;
10 'OSBuild'=$os.buildnumber}
11 New-Object -TypeName PSObject -Property $props
12 }
Esta es una función sencilla, y la principal razón por la que me molesté en hacer que sea una función - en lugar de simplemente usar Get-WmiObject directamente - es que quiero nombres de propiedad diferentes, como “OSVersion” en lugar de sólo “Version”. Dicho esto, tiendo a seguir exactamente este mismo patrón de programación para todas las funciones de recuperación de información, sólo para mantenerlas consistentes.
1 function Get-InfoCompSystem {
2 [CmdletBinding()]
3 param(
4 [Parameter(Mandatory=$True)][string]$ComputerName
5 )
6 $cs = Get-WmiObject -class Win32_ComputerSystem -Comp\
7 uterName $ComputerName
8 $props = @{'Model'=$cs.model;
9 'Manufacturer'=$cs.manufacturer;
10 'RAM (GB)'="{0:N2}" -f ($cs.totalphysicalm\
11 emory / 1GB);
12 'Sockets'=$cs.numberofprocessors;
13 'Cores'=$cs.numberoflogicalprocessors}
14 New-Object -TypeName PSObject -Property $props
15 }
Muy similar a la anterior. Notará aquí que estoy usando el operador de formato -f con la propiedad RAM, de modo que obtengo un valor en gigabytes con 2 decimales. El valor nativo está en bytes, lo que no es útil para mí.
1 function Get-InfoBadService {
2 [CmdletBinding()]
3 param(
4 [Parameter(Mandatory=$True)][string]$ComputerName
5 )
6 $svcs = Get-WmiObject -class Win32_Service -ComputerN\
7 ame $ComputerName `
8 -Filter "StartMode='Auto' AND State<>'Running'"
9 foreach ($svc in $svcs) {
10 $props = @{'ServiceName'=$svc.name;
11 'LogonAccount'=$svc.startname;
12 'DisplayName'=$svc.displayname}
13 New-Object -TypeName PSObject -Property $props
14 }
15 }
Aquí, he tenido que reconocer que voy a estar recuperando más de un objeto de WMI, así que tengo que enumerar a través de ellos usando una construcción ForEach. Una vez más, estoy principalmente renombrando propiedades. Podría haber hecho eso con un comando Select-Object, pero me gusta mantener la estructura de funciones general similar a mis otras funciones. Es sólo una preferencia personal que me ayuda a incluir menos errores, ya que estoy acostumbrado a hacer las cosas de esta manera.
1 function Get-InfoProc {
2 [CmdletBinding()]
3 param(
4 [Parameter(Mandatory=$True)][string]$ComputerName
5 )
6 $procs = Get-WmiObject -class Win32_Process -Computer\
7 Name $ComputerName
8 foreach ($proc in $procs) {
9 $props = @{'ProcName'=$proc.name;
10 'Executable'=$proc.ExecutablePath}
11 New-Object -TypeName PSObject -Property $props
12 }
13 }
Muy similar a la función de servicios. Probablemente pueda empezar a notar cómo usar esta misma estructura hace que una cierta cantidad “copiar y pegar” se vuelva efectiva cuando creo una nueva función.
1 function Get-InfoNIC {
2 [CmdletBinding()]
3 param(
4 [Parameter(Mandatory=$True)][string]$ComputerName
5 )
6 $nics = Get-WmiObject -class Win32_NetworkAdapter -Co\
7 mputerName $ComputerName `
8 -Filter "PhysicalAdapter=True"
9 foreach ($nic in $nics) {
10 $props = @{'NICName'=$nic.servicename;
11 'Speed'=$nic.speed / 1MB -as [int];
12 'Manufacturer'=$nic.manufacturer;
13 'MACAddress'=$nic.macaddress}
14 New-Object -TypeName PSObject -Property $props
15 }
16 }
Lo principal para notar aquí es cómo he convertido la propiedad speed, que esta nativamente en bytes, a megabytes. Debido a que no me interesan los decimales aquí (quiero un número entero), eligo utilizar el valor como un entero, utilizando el operador -as, que es más sencillo para mí que el operador de formato -f. ¡Además, me da la oportunidad de mostrar esta técnica!
Tenga en cuenta que, a los efectos de este libro, voy a poner estas funciones en el mismo archivo de script que el resto de mi código, lo que en realidad genera el código HTML. Normalmente no hago eso. Normalmente, las funciones de recuperación de información van a un módulo de script, y entonces escribo mi script de generación HTML para cargar ese módulo. Tener las funciones en un módulo hace que sean más fáciles de usar en otros lugares, si quiero. Estoy omitiendo el módulo esta vez sólo para mantener las cosas más simples en esta demostración. Si desea obtener más información sobre los módulos de script, debería dar una mirada a Learn PowerShell Toolmaking in a Month of Lunches o PowerShell in Depth, los cuales están disponibles en Manning.com.