El Blog de Gualtrysoft

Windows 2000/2003/2008, Active Directory, VBScript, Hyper-V, PowerShell y todo aquello interesante a la hora de usar, configurar y administrar Windows Server. También tenemos longanizas…

PowerShell: Cmdlet para obtener información sobre la memoria física de un equipo (2)

Posted by urpiano en Jueves 9 \09\UTC diciembre \09\UTC 2010

Esta función de PowerShell obtiene información sobre la memoria física de un equipo, local o remoto, en base a una consulta WMI a la clase Win32_PhysicalMemory. La función permite recibir el nombre del equipo a mirar por encaminamiento, lo que permite encaminar toda un conjunto de equipos y obtener un listado de memoria física.

Se trata del mismo Cmdlet Get-PhysicalMemory publicado anteriormente pero usando Get-WmiExpression; si comparamos esta versión con la anterior, veremos cómo el uso de Get-WmiExpression ha permitido que el código sea más claro y sin repeticiones.

El Cmdlet incluye ayuda, pego a continuación la ayuda con modificador -Detailed (esta ayuda se basa en la prestación de ayuda basada en comentarios de PowerShell 2.0 ¿Qué todavía tienes la versión 1.0 y no la 2.0? ¿A qué esperas para instalarla si es mucho mejor?):

NOMBRE
    Get-PhysicalMemory
    
SINOPSIS
    Devuelve información sobre la memoria física de la máquina.
    
SINTAXIS
    Get-PhysicalMemory [[-ComputerName] <String>] [[-Credential] <Object>] [<CommonParameters>]
    
DESCRIPCIÓN
    Este Cmdlet permite obtener el información sobre la memoria física de la
    máquina recibida como parámetro o de la máquina local si se omite este
    parámetro. La información es obtenida procesando la clase WMI
    Win32_PhysicalMemory del espacio de nombres root/CIMv2. La función permite
    especificar las credenciales con las que se conectará a WMI, credenciales
    que serán ignoradas en el caso del equipo local, pues no se puede acceder a
    WMI con credenciales alternativas desde el equipo local.
    
    La devolución de la función consiste en objetos cuyas propiedades son:
       - Equipo:  Nombre del equipo del que se obtiene información de la memoria
                  física.
       - Modulos: Recuento de tipos de módulos que hay en la máquina, por tamaño
                  expresado en MegaBytes. El formato de este campo es
                  (tamaño1*nºmódulos)MB;(tamaño2*nºmódulos)MB;....
       - TotalMB: Tamaño total de la memoria, obtenido al sumar el tamaño de los
                  los módulos que la integran.
       - Error:   Si se produce un error al intentar obtener la información,
                  esta propiedad contiene el error que se produjo. Si no se
                  produjo error, el valor de esta propiedad es $null
    
    La función permite canalización, admitiendo como entrada nombres o IPs de
    equipos
    
PARÁMETROS
    -ComputerName <String>
        Nombre o IP del equipo al que se consultará. Tiene también los alias
        "Equipo","Sistema","E","C" y "S".
        
    -Credential <Object>
        Nombre de usuario o credenciales completas del usuario con el que se
        conectara a WMI. En caso de pasarse sólo el nombre de usuario, se pedirá
        entrar la contraseña del mismo. Si se pasan credenciales y se consulta el
        equipo local, las credenciales serán ignoradas, pues no se puede conectar
        a WMI del equipo local con credenciales alternativas. Tiene también los
        alias "Usuario","U","Credenciales" y "Cred".
        
    <CommonParameters>
        Este cmdlet admite los parámetros comunes Verbose, Debug,
        ErrorAction, ErrorVariable, WarningAction, WarningVariable,
        OutBuffer y OutVariable. Para obtener más información, escriba:
        "get-help about_commonparameters".
    
    -------------------------- EJEMPLO 1 --------------------------
    
    PS >Get-PhysicalMemory
    
    Muestra por pantalla la memoria física del equipo local.
    
    -------------------------- EJEMPLO 2 --------------------------
    
    PS >Get-PhysicalMemory -ComputerName Mortadelo-PC
    
    Muestra por pantalla la memoria física del equipo de nombre Mortadelo-PC.
    
    -------------------------- EJEMPLO 3 --------------------------
    
    PS >Get-PhysicalMemory -C Mortadelo-PC -Credential TIA\Bacterio
    
    Muestra por pantalla la memoria física del equipo de nombre Mortadelo-PC,
    conectando a WMI con el usuario TIA\Bacterio; se solicitará la contraseña
    de dicho usuario.
    
    -------------------------- EJEMPLO 4 --------------------------
    
    PS >"Mortadelo-PC","Filemon-PC" | Get-PhysicalMemory -Cred TIA\Bacterio
    
    Muestra por pantalla la memoria física de los equipos de nombre Mortadelo-PC
    y Filemon-PC, conectando a WMI con el usuario TIA\Bacterio; se solicitará la
    contraseña de dicho usuario.
    
    -------------------------- EJEMPLO 5 --------------------------
    
    PS >$Usuario = Get-Credential
    PS >"Mortadelo-PC","Filemon-PC" | Get-PhysicalMemory -Usuario $Usuario

    Muestra por pantalla la memoria física de los equipos de nombre Mortadelo-PC
    y Filemon-PC, conectando a WMI con el usuario establecido previamente con
    Get-Credential en la variable $Usuario.
    
    -------------------------- EJEMPLO 6 --------------------------
    
    PS >$Usr = Get-Credential
    PS >Get-Content c:\Equipos.txt | Get-PhysicalMemory -U $Usr | Export-CSV c:\Mem.csv

    Este ejemplo muestra una manera muy útil de usar esta función. Guarda, en el
    fichero de valores separados por coma c:\Mem.csv, un listado con la memoria
    física  de los equipos listados en el fichero de texto c:\Equipos.txt, que
    contiene un nombre de equipo por línea, conectando a WMI con el usuario,
    establecido previamente con Get-Credential, en la variable $Usr.

Este es el código del Cmdlet:

Function Get-PhysicalMemory([parameter(position=0,
                               ValueFromPipeLine=$True,
                               HelpMessage="Nombre de equipo.")]
                        [Alias("Equipo","Sistema","E","C","S")]
                        [String]$ComputerName = "$($env:ComputerName)",
                    [parameter(Position=1,
                             Mandatory=$false,
                             HelpMessage="Credenciales de usuario de conexión")]
                        [Alias("Usuario","U","Credenciales","Cred")]
                        $Credential)
{
    Begin
    {
        $Devolucion = @()
        # Si no se han pasado unas credenciales completas, si no sólo un nombre
        # de usuario, hay que llamar a Get-Credential para obtenerlas completas
        If($Credential -ne $null -and `
          ($Credential.GetType()).Name -ne "PsCredential")
        {
                $Credential = Get-Credential $Credential
        }
    }
    Process
    {
        # Si se recibió como nombre de equipo un punto, esto implica el equipo
        # local; sustituimos el punto por el nombre de equipo
        If($ComputerName -eq "."){$ComputerName = "$($env:ComputerName)"}
        # Iniciamos el comando que obtendrá la memoria física del equipo consultando
        # WMI, en concreto la clase Win32_PhysicalMemory del espacio de nombres
        # CIMv2
        $Comando = "Get-WmiObject Win32_PhysicalMemory"
        $Comando = "$Comando -Namespace root/CIMv2"
        # Agregamos el nombre de equipo
        $Comando = "$Comando -ComputerName $ComputerName"
        # Invocamos el comando montado para obtener la lista de discos,
        # interceptando errores
        # Obtenemos los módulos de memoria del equipo
        $Modulos = Invoke-WmiExpression -Expression $Comando `
                                        -Credential $Credential
        # Si no es nula la devolución, es porque ha habido éxito en la consulta
        # WMI
        If($Modulos -ne $null)
        {
            # Iniciamos el Hash del recuento, en el que las claves serán los
            # diferentes tamaños, en MB, de los módulos y el valor será el
            # número de módulos de cada tamaño
            $Recuento = @{}
            # Recorremos los módulos
            ForEach($Modulo In $Modulos)
            {
                # Si ya está como clave el tamaño del módulo actual, sumamos uno
                # al valor de la clave
                If($Recuento.Keys -contains ($Modulo.Capacity/1mb))
                {
                    $Recuento.(($Modulo.Capacity/1mb))++
                }
                # Como no existe esa clave, la agregamos con valor uno
                Else
                {
                    $Recuento += @{($Modulo.Capacity/1mb) = 1}
                }
            }
            # Creamos el objeto devolución de la función
            $Resultado = New-Object PsObject
            # Iniciamos la variable que contendrá el total de capacidad de los
            # módulos
            $Total = 0
            # Iniciamos el resumen
            $Resumen = ""
            # Recorremos los elementos del Hash de tamaños
            ForEach($Clave In $Recuento.Keys)
            {
                # Agregamos al total el producto de la clave (que es el tamaño
                # del tipo de módulo) por el valor (que es el número de módulos
                # del tamaño reflejado por la clave)
                $Total = $Total + ($Clave * $Recuento.($Clave))
                # Agregamos al resumen el tamaño de módulo y el número de
                # módulos y agregamos un punto y coma; la idea es que se
                # presente como una cadena de este estilo:
                # (1024*2)MB;(2048*2)MB
                $Resumen = "$Resumen($Clave*$($Recuento.($Clave)))MB;"
            }
            # Si se ha obtenido devolución, sobre el último punto y coma, por
            # ello lo quitamos
            If($Resumen.Length -gt 0)
            {
                $Resumen = $Resumen.SubString(0,$Resumen.Length-1)
            }
            # Agregamos a la devolución el nombre del equipo
            Add-Member -InputObject $Resultado `
                       -MemberType NoteProperty `
                       -Name Equipo `
                       -Value $ComputerName
            # Agregamos el resumen de módulos
            Add-Member -InputObject $Resultado `
                       -MemberType NoteProperty `
                       -Name Modulos `
                       -Value $Resumen
            # Agregamos el tamaño total en MB
            Add-Member -InputObject $Resultado `
                       -MemberType NoteProperty `
                       -Name TotalMB `
                       -Value $Total
            # Agregamos un nulo como error
            Add-Member -InputObject $Resultado `
                       -MemberType NoteProperty `
                       -Name Error `
                       -Value $null
            $Devolucion += $Resultado
        }
        Else
        {
            Write-Host "$ComputerName`: $($Error[0].Exception.Message)" `
                       -ForegroundColor Red
            # Como se produce error generaremos un resultado en el que
            # todo tendrá valor nulo excepto el nombre del equipo y el
            # error que se ha producido. Por tanto, creamos un objeto
            # para el resultado
            $Resultado = New-Object PsCustomObject
            # Agregamos el nombre del equipo
            Add-Member -InputObject $Resultado `
                    -MemberType NoteProperty `
                    -Name Equipo `
                    -Value $ComputerName
            # Agregamos el resumen de módulos
            Add-Member -InputObject $Resultado `
                    -MemberType NoteProperty `
                    -Name Modulos `
                    -Value $null
            # Agregamos el tamaño total en MB
            Add-Member -InputObject $Resultado `
                    -MemberType NoteProperty `
                    -Name TotalMB `
                    -Value $null
            # Agregamos el error que se produjo
            Add-Member -InputObject $Resultado `
                    -MemberType NoteProperty `
                    -Name Error `
                    -Value $Error[0].Exception.Message
            $Devolucion += $Resultado
        }
        # Restituimos la acción que estaba configurada para los errores que
        # no interrumpen
        $ErrorActionPreference = $AccionError
    }
    End
    {
        $Devolucion
    }
#.SYNOPSIS
#   Devuelve información sobre la memoria física de la máquina.
#.DESCRIPTION
#   Este Cmdlet permite obtener el información sobre la memoria física de la
#   máquina recibida como parámetro o de la máquina local si se omite este
#   parámetro. La información es obtenida procesando la clase WMI
#   Win32_PhysicalMemory del espacio de nombres root/CIMv2. La función permite
#   especificar las credenciales con las que se conectará a WMI, credenciales
#   que serán ignoradas en el caso del equipo local, pues no se puede acceder a
#   WMI con credenciales alternativas desde el equipo local.
#   
#   La devolución de la función consiste en objetos cuyas propiedades son:
#      - Equipo:  Nombre del equipo del que se obtiene información de la memoria
#                 física.
#      - Modulos: Recuento de tipos de módulos que hay en la máquina, por tamaño
#                 expresado en MegaBytes. El formato de este campo es
#                 (tamaño1*nºmódulos)MB;(tamaño2*nºmódulos)MB;....
#      - TotalMB: Tamaño total de la memoria, obtenido al sumar el tamaño de los
#                 los módulos que la integran.
#      - Error:   Si se produce un error al intentar obtener la información,
#                 esta propiedad contiene el error que se produjo. Si no se
#                 produjo error, el valor de esta propiedad es $null
#
#   La función permite canalización, admitiendo como entrada nombres o IPs de
#   equipos
#.PARAMETER ComputerName
#   Nombre o IP del equipo al que se consultará. Tiene también los alias
#   "Equipo","Sistema","E","C" y "S".
#.PARAMETER Credential
#   Nombre de usuario o credenciales completas del usuario con el que se
#   conectara a WMI. En caso de pasarse sólo el nombre de usuario, se pedirá
#   entrar la contraseña del mismo. Si se pasan credenciales y se consulta el
#   equipo local, las credenciales serán ignoradas, pues no se puede conectar
#   a WMI del equipo local con credenciales alternativas. Tiene también los
#   alias "Usuario","U","Credenciales" y "Cred".
#.NOTES
#   Desarrollado por Fernando Reyes López
#   Noviembre de 2010
#.LINK
#   http://freyes.svetlian.com -> Artículos de Fernando reyes
#.LINK
#   https://urpiano.wordpress.com -> El Blog de GualtrySoft
#.EXAMPLE
#     PS >Get-PhysicalMemory
#   Muestra por pantalla la memoria física del equipo local.
#.EXAMPLE
#     PS >Get-PhysicalMemory -ComputerName Mortadelo-PC
#   Muestra por pantalla la memoria física del equipo de nombre Mortadelo-PC.
#.EXAMPLE
#     PS >Get-PhysicalMemory -C Mortadelo-PC -Credential TIA\Bacterio
#   Muestra por pantalla la memoria física del equipo de nombre Mortadelo-PC,
#   conectando a WMI con el usuario TIA\Bacterio; se solicitará la contraseña
#   de dicho usuario.
#.EXAMPLE
#     PS >"Mortadelo-PC","Filemon-PC" | Get-PhysicalMemory -Cred TIA\Bacterio
#   Muestra por pantalla la memoria física de los equipos de nombre Mortadelo-PC
#   y Filemon-PC, conectando a WMI con el usuario TIA\Bacterio; se solicitará la
#   contraseña de dicho usuario.
#.EXAMPLE
#     PS >$Usuario = Get-Credential
#     PS >"Mortadelo-PC","Filemon-PC" | Get-PhysicalMemory -Usuario $Usuario
#   Muestra por pantalla la memoria física de los equipos de nombre Mortadelo-PC
#   y Filemon-PC, conectando a WMI con el usuario establecido previamente con
#   Get-Credential en la variable $Usuario.
#.EXAMPLE
#     PS >$Usr = Get-Credential
#     PS >Get-Content c:\Equipos.txt | Get-PhysicalMemory -U $Usr | Export-CSV c:\Mem.csv
#   Este ejemplo muestra una manera muy útil de usar esta función. Guarda, en el
#   fichero de valores separados por coma c:\Mem.csv, un listado con la memoria
#   física  de los equipos listados en el fichero de texto c:\Equipos.txt, que
#   contiene un nombre de equipo por línea, conectando a WMI con el usuario,
#   establecido previamente con Get-Credential, en la variable $Usr.
}

Function Invoke-WmiExpression([string]$Expression,$Credential)
{
    # Si se ha recibido credenciales, las añadimos al comando
    If($Credential -ne $null -and `
      ($Credential.GetType()).Name -eq "PsCredential")
    {
        # Guadamos el comando sin credenciales
        $ExpressionNoCredential = $Expression
        # Agregamos las credenciales al comando
        $Expression = "$Expression -Credential `$Credential"
    }
    # Limpiamos la variable de errores
    $Error.Clear()
    # Nos guardamos la configuración existente ante los errores que no
    # interrumpen
    $AccionError = $ErrorActionPreference
    # Establecemos que los errores que no interrumpen sí lo hagan, así
    # podremos capturarlos con Try/Catch
    $ErrorActionPreference = "Stop"
    Try
    {
        # Obtenemos los módulos de memoria del equipo
        $Devolucion = Invoke-Expression $Expression
    }
    Catch
    {
        # Si el error producido es provocado porque se ha intentado
        # pasar credenciales al equipo local...
        If($Error[0].Exception.ErrorCode -eq "LocalCredentials")
        {
            # Restituimos el comando para que sea sin pedir credenciales
            $Expression = $ExpressionNoCredential
            # Volvemos a invocar el comando para obtener los volúmenes
            $Devolucion = Invoke-Expression $Expression
        }
        Else
        {
            $Devolucion = $null
        }
    }
    # Restituimos la acción que estaba configurada para los errores que
    # no interrumpen
    $ErrorActionPreference = $AccionError
    $Devolucion
#.SYNOPSIS
#   Devuelve el resultado de una llamada que se hace a Get-WmiObject con la
#   cadena que se recibe como parámetro y que es pasada a Execute-Expression,
#   realizando control de errores.
#.DESCRIPTION
#   La princpal tarea de esta función es evitar la redundancia de código que
#   se produce al controlar el error que se genera si se realiza una llamada
#   a Get-WmiObject con credenciales alternativas al equipo local. En toda
#   función que realice este tipo de llamadas y que se quiera controlar este 
#   error, cuando usamos Try/Catch, el bloque de la función se coloca en la
#   parte Try y en el Catch hay que controlar si el error es por las
#   credenciales alternativas y en caso afirmativo volver a invocar
#   Get-WmiObject sin pasarlas, para a continuación volver a poner el bloque de
#   código, lo que lo duplica. En el código de la función que usa ésta, sólo se
#   tendrá que poner el bloque principal una vez, pues se convierte en
#   transparente si es el equipo local o no.
#.PARAMETER Expression
#   Cadena que es una llamada a Get-WmiObject.
#.PARAMETER Credential
#   Nombre de usuario o credenciales completas del usuario con el que se
#   conectara a WMI. En caso de pasarse sólo el nombre de usuario, se pedirá
#   entrar la contraseña del mismo. Si se pasan credenciales y se consulta el
#   equipo local, las credenciales serán ignoradas, pues no se puede conectar
#   a WMI del equipo local con credenciales alternativas. Tiene también los
#   alias "Usuario","U","Credenciales" y "Cred".
#.NOTES
#   Desarrollado por Fernando Reyes López
#   Noviembre de 2010
#.LINK
#   http://freyes.svetlian.com -> Artículos de Fernando reyes
#.LINK
#   https://urpiano.wordpress.com -> El Blog de GualtrySoft
#.EXAMPLE
#     PS >Invoke-WmiExpression "Get-WmiObject Win32_Process -ComputerName mortadelo-pc" -Credential (Get-Credential TIA\Bacterio)
#   Muestra por pantalla los procesos del equipo mortadelo-pc, pasando las
#   credenciales de un prestigioso científico y no importando si se trata del
#   equipo local o no; se pedirá al insigne profesor que entre su contraseña.
#.EXAMPLE
#     PS >$Usr = Get-Credential
#     PS >Invoke-WmiExpression "Get-WmiObject Win32_Process -ComputerName mortadelo-pc" -Credential (Get-Credential TIA\Bacterio)
#   Muestra por pantalla los procesos del equipo mortadelo-pc, pasando las
#   credenciales contenidas en $Usr y que fueron obtenidas invocando
#   Get-Credential.
}

Una respuesta to “PowerShell: Cmdlet para obtener información sobre la memoria física de un equipo (2)”

  1. […] PowerShell: Cmdlet para obtener información sobre la memoria física de un equipo (2) […]

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

 
A %d blogueros les gusta esto: