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 enviar un correo con la información de la última sincronización de los servidores WSUS

Publicado por urpiano en Martes 12 \12\UTC febrero \12\UTC 2013

¿Quieres crear una tarea programada que todos los días te informe de qué tal ha ido la sincronización de tus servidores WSUS? Este Cmdlet de Powershell te puede ser útil.

Este es un ejemplo del informe que se recibe:

Este es el estado de la sincronización en la plataforma de WSUS obtenido el 12 de febrero de 2013 a las 07:00

Servidor Precedente HoraInicio HoraFinal Minutos TipoSinc Resultado Error
alicante.tia.org wsustia.tia.org 12/02/2013
01:00:05
12/02/2013
01:01:12
1,13 Automática Succeeded Ninguno
barcelona.tia.org wsustia.tia.org 11/02/2013
23:00:00
11/02/2013
23:01:28
1,47 Automática Succeeded Ninguno
calpe.tia.org wsustia.tia.org 11/02/2013
19:00:01
11/02/2013
19:01:20
1,31 Automática Succeeded Ninguno
ecija.tia.org wsustia.tia.org 11/02/2013
19:00:03
11/02/2013
19:01:26
1,38 Automática Succeeded Ninguno
formentera.tia.org wsustia.tia.org 11/02/2013
19:00:05
11/02/2013
19:01:47
1,71 Automática Succeeded Ninguno
valencia.trabajo.dom wsustia.tia.org 12/02/2013
00:30:02
12/02/2013
00:31:51
1,81 Automática Succeeded Ninguno
wsustia.tia.org Microsoft Update 11/02/2013
18:12:04
11/02/2013
18:13:17
1,23 Automática Succeeded Ninguno
wsustia2.tia.org wsustia.tia.org 11/02/2013
20:00:00
11/02/2013
20:01:08
1,13 Automática Succeeded Ninguno
 

 

El Cmdlet utiliza los ensamblados de WSUS, que están presentes en aquellos equipos a los que se ha instalado la consola de administración de WSUS, ya sea un servidor WSUS u otro equipo no servidor al que se le haya instalado las herramientas de administración de WSUS. Para poder acceder a los datos de los servidores remotos, es necesario que éstos tengan publicado en el firewall los puertos de HTTP y HTTPS, ya sean los predeterminados o los puertos en los que se haya instalado el sitio Web de WSUS de los servidores.

Como parámetro de servidor WSUS se le debe pasar el del servidor WSUS raíz, para que así revise toda la infraestructura de WSUS que se tenga desplegada.

Si el Cmdlet se ejecuta en un servidor WSUS, es necesario que se haga con elevación de privilegios.

Se puede lanzar especificando como mínimo el servidor WSUS raíz, el servidor de correo desde el que se envían los resultados, los destinatarios y el remitente; el asunto del correo y el texto de encabezado son opcionales. Un ejemplo de cómo se lanza sería:

PS> Send-WsusSynchronizationStatus -WsusServer wsustia -SmtpServer smtptia `
                                   -To "filemonpi@tia.org","Superintendente Vicente<vicente@tia.org>" `
                                   -From "Profesor Bacterio<pbacterio@tia.org>"

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
    Send-WsusSynchronizationStatus

SINOPSIS
    Envía un correo con la información sobre la última sincronización de los
    servidores de WSUS.

SINTAXIS
    Send-WsusSynchronizationStatus [[-WsusServer]] [[-SmtpServer]] [[-To] <String[]>] [[-From]] [[-Subject]] [[-BodyHeader]] []

DESCRIPCIÓN
    Este Cmdlet permite enviar un correo con la información de los
    resultados de la última sincronización de la plataforma de WSUS cuyo servidor
    raíz es el recibido como parámetro. El correo enviado es en formato HTML.

PARÁMETROS
    -WsusServer
        Este parámetro establece el nombre del servidor WSUS al que se conectará
        para obtener información de él y sus descendientes en la cadena.

    -SmtpServer
        Este parámetro establece el servidor SMTP que se usará para enviar el
        correo

    -To <String[]>
        Este parámetro establece el remitente como dirección de correo SMTP. Una
        dirección de coreo SMTP puede ser de dos maneras:
                    - NombreParaMostrar (Ejemplo "Pi, Filemón<fpi@tia.org>").
                    - correo (Ejemplo "fpi@tia.org")

    -From
        Este parámetro establece los destinatarios como direcciones de de correo
        SMTP.

    -Subject
        Este parámetro establece el asunto del correo.

    -BodyHeader 
        Este parámetro establece el texto de introducción del cuerpo del
        mensaje. Será incluído en un párrafo (<p>) con la alineación justificada.

    
        Este cmdlet admite los parámetros comunes Verbose, Debug,
        ErrorAction, ErrorVariable, WarningAction, WarningVariable,
        OutBuffer y OutVariable. Para obtener más información, consulte
        about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).

    -------------------------- EJEMPLO 1 --------------------------
    PS C:\>Send-WsusSynchronizationStatus -WsusServer "wsus.tia.org" `
                     -SmtpServer "smtp.tia.org" `
                     -To "Vicente, Superintendente", `
                         "Bacterio, Profesor" `
                     -From "Pi, Filemón" `
                     -Subject "Estado de WSUS $((Get-Date).ToString("yyyyMMdd"))" `
                     -BodyHeader "Asín están las cosas en WSUS."

NOTAS
    Para ver los ejemplos, escriba: "get-help Send-WsusSynchronizationStatus -examples".
    Para obtener más información, escriba: "get-help Send-WsusSynchronizationStatus -detailed".
    Para obtener información técnica, escriba: "get-help Send-WsusSynchronizationStatus -full".
    Para obtener ayuda disponible en línea, escriba: "get-help Send-WsusSynchronizationStatus -online"

Esta es la ayuda de la función auxiliar que permite cargar un ensamblado, que se usa para cargar los ensamblados de WSUS:

NOMBRE
    Load-Assembly

SINOPSIS
    Carga un ensamblado a partir de su nombre parcial

SINTAXIS
    Load-Assembly [[-Assembly] ] []

DESCRIPCIÓN
    Este Cmdlet carga el ensamblado cuyo nombre parcial es el recibido como
    parámetro. El Cmdlet comprueba previamente si el ensamblado ha sido ya cargado,
    y en caso contrario lo carga.

PARÁMETROS
    -Assembly 
        Nombre parcial del ensamblado a cargar.

        Este cmdlet admite los parámetros comunes Verbose, Debug,
        ErrorAction, ErrorVariable, WarningAction, WarningVariable,
        OutBuffer y OutVariable. Para obtener más información, consulte
        about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).

    -------------------------- EJEMPLO 1 --------------------------
    PS C:\>Load-Assembly "Microsoft.UpdateServices.Administration"

NOTAS
    Para ver los ejemplos, escriba: "get-help Load-Assembly -examples".
    Para obtener más información, escriba: "get-help Load-Assembly -detailed".
    Para obtener información técnica, escriba: "get-help Load-Assembly -full".
    Para obtener ayuda disponible en línea, escriba: "get-help Load-Assembly -online"

Este es el código del Cmdlet:

Function Load-Assembly([String]$Assembly)
{
    $Assemblies = [AppDomain]::CurrentDomain.GetAssemblies() | `
                                            ForEach{$_.ToString().Split(",")[0]}
    If($Assemblies -notcontains $Assembly)
    {
        Try
        {
            [Reflection.Assembly]::LoadWithPartialName($Assembly) | Out-Null
            Return $true
        }
        Catch
        {
            Return $false
        }
    }

<#
    .SYNOPSIS
        Carga un ensamblado a partir de su nombre parcial

    .DESCRIPTION
        Este Cmdlet carga el ensamblado cuyo nombre parcial es el recibido como
parámetro. El Cmdlet comprueba previamente si el ensamblado ha sido ya cargado,
y en caso contrario lo carga.

    .PARAMETER  Assembly
        Nombre parcial del ensamblado a cargar.

    .EXAMPLE
        PS C:\> Load-Assembly "Microsoft.UpdateServices.Administration"

    .INPUTS
        System.String
    
    .OUTPUTS
        None

    .NOTES
        12/2012 © Fernando Reyes López

    .LINK

http://freyes.svetlian.com

    .LINK

http://urpiano.wordpress.com

#>

}

Function Send-WsusSynchronizationStatus(
                        [String]$WsusServer="WSUS.trabajo.dom",
                        [String]$SmtpServer="exchvhub.trabajo.dom",
                        [String[]]$To="SGPD-Des-Sistemas2@meyss.es",
                        [String]$From="WsusAdmin@meyss.es",
                        [String]$Subject="Estado de replicación de " + `
                                 "WSUS el $((Get-Date).ToString("dd/MM/yyyy"))",
                        [String]$BodyHeader="Este es el estado de la " + `
                                       "sincronización en la plataforma de " + `
                                       "WSUS obtenido el " + `
                  "$((Get-Date).ToString("dd \de MMMM \de yyyy a la\s HH:mm"))")
{
    # Cargamos el ensamblado de WSUS si es necesario
    Load-Assembly "Microsoft.UpdateServices.Administration"
    
    # Iniciamos la variable que albergará la colección de resultados de
    # sincronización de los servidores
    $Resultado = @()
    
    # Iniciamos la variable que contrendrá los nombres de los servidores
    $Servidores = New-Object System.Collections.ArrayList
    
    # Agregamos el servidor raíz a la lista de servidores
    [Void]$Servidores.Add($WsusServer)
    
    # Almacenamos una referencia a la clase AdminProxy, necesaria para obtener
    # los objetos de servidor WSUS
    $AdminProxy = [Microsoft.UpdateServices.Administration.AdminProxy]

    #Obtenemos el servidor WSUS recibido como parámetro
    $WSUS = $AdminProxy::getUpdateServer($WsusServer,$false)
    
    # Obtenemos los servidores que siguen en la cadena al servidor recibido como
    # parámetro. Uno a uno, iremos obteniendo su objeto y agregándolo a la
    # lista de servidores
    $WSUS.GetDownstreamServers()|ForEach{ `
        Write-Host $_.FullDomainName -BackgroundColor Blue -ForegroundColor Yellow
        [Void]$Servidores.Add($_.FullDomainName)
    }
    
    # Ordenamos la lista de servidores
    $Servidores.Sort()
    
    # Recorremos la lista de servidores
    $Servidores | ForEach{ `
        # Almacenamos el servidor actual, para evitar el perder su referencia en
        # futuras canalizaciones
        $NombreServidor = $_
        
        # Intentaremos obtener el objeto UpdateServer del servidor actual, en una
        # estructura Try/Catch por si hubiera problemas de comunicación,
        # disponibilidad, etc.
        Try
        {
            # Obtenemos el objeto UpdateServer del servidor actual
            $Servidor = $AdminProxy::getUpdateServer($NombreServidor,$false)
            # Obtenemos la información de la última sincronización
            $Registro = $Servidor.GetSubscription().GetLastSynchronizationInfo()
            
            # Guardamos el nombre del servidor
            $Nombre = "$($Servidor.Name.ToLower())"
            
            # Guardamos si la sincronización fue manual o automática
            If($Registro.StartedManually){$Tipo = "Manual"}
            Else{$Tipo = "Automática"}
            
            # Guardamos el destino de la sincronización. Para ello primero se mira
            # si el servidor está configurado para sincronizar desde Microsoft
            # Update, según sea True o False su propiedad de configuración
            # SyncFromMicrosoftUpdate
            If($Servidor.GetConfiguration().SyncFromMicrosoftUpdate)
            {
                # El servidor sincroniza desde Microsoft Update
                $Precedente = "Microsoft Update"
            }
            Else
            {
                # El servidor no sincroniza desde Microsoft Update; almacenamos el
                # servidor precedente en la cadena desde el cual sincroniza, que
                # es el que almacena su propiedad de configuración
                # UpstreamWsusServerName
                $Precedente = `
                       $Servidor.GetConfiguration().UpstreamWsusServerName.ToLower()
            }
            # Agregamos a la información de la última sincronización el nombre del
            # servidor, el tipo de sincronización (manual o automática) y el
            # servidor desde el cual se sincroniza (Microsoft Update o el predecesor
            # en la cadena)
            $Resultado += $Registro | 
                      Select-Object *,@{Label="Servidor";Expression={$Nombre}}, `
                                      @{Label="Tipo";Expression={$Tipo}}, `
                                      @{Label="Precedente";Expression={$Precedente}}
        }
        Catch
        {
            # Se ha producido un error al intentar obtener el objeto UpdateServer
            # del servidor actual. Creamos un objeto PsCustomObjet
            $Registro = New-Object PsCustomObject
            
            # Agregamos al objeto las propiedades que se muestran en los resultados
            $Registro = $Registro | Select-Object Servidor,Precedente,StartTime,EndTime,Tipo,Result,ErrorText
            
            # Ponemos el nombre del servidor
            $Registro.Servidor = $NombreServidor.ToLower()
            
            #  Ponemos el resto de propiedades, excepto el error, como "N/A"
            $Registro.Precedente = "N/A"
            $Registro.StartTime = "N/A"
            $Registro.EndTime = "N/A"
            $Registro.Tipo = "N/A"
            $Registro.Result = "N/A"
            
            # Si hay mensaje de excepcción interna, es el que guardaremos como texto
            # de error, si no, guardaremos el resultado del método ToString sobre el
            # propio error
            If([string]::IsNullOrEmpty($Error[0].Exception.InnerException.Message))
            {
                $ElError = $Error[0].ToString()
            }
            Else
            {
                $ElError = $Error[0].Exception.InnerException.Message
            }
            $Registro.ErrorText = $ElError
            
            # Agregamos la información a los resultados
            $Resultado += $Registro
        }
    }
    # Una vez obtenidos los datos, montamos el HTML del cuerpo del mensaje de
    # correo.
    # Vamos a definir estilos CSS
    $Tabla = "style=`"background-color:sienna;color:LightGoldenRodYellow;bo" + `
             "rder-collapse:collapse;`""
    $EncabezadoDerecha = "style=`"border-left:0px none gold;border-top:5px " + `
                         "ridge gold;border-bottom:5px ridge gold;border-ri" + `
                         "ght:5px ridge gold;`""
    $EncabezadoCentro = "style=`"border-left:0px none gold;border-top:5px r" + `
                        "idge gold;border-bottom:5px ridge gold;border-righ" + `
                        "t:0px none gold;`""
    $EncabezadoIzquierda = "style=`"border-left:5px ridge gold;border-top:5" + `
                           "px ridge gold;border-bottom:5px ridge gold;bord" + `
                           "er-right:0px none gold;`""
    $CeldaIzquierda = "style=`"padding:1px 6px;border-left:5px ridge gold;b" + `
                      "order-top:3px ridge gold;border-bottom:3px ridge gol" + `
                      "d;border-right:3px groove gold;`""
    $CeldaCentro = "style=`"padding:1px 6px;border-left:3px groove gold;bor" + `
                   "der-top:3px ridge gold;border-bottom:3px ridge gold;bor" + `
                   "der-right:3px groove gold;`""
    $CeldaDerecha = "style=`"padding:1px 6px;border-left:3px groove gold;bo" + `
                    "rder-top:3px ridge gold;border-bottom:3px ridge gold;b" + `
                    "order-right:5px ridge gold;`""
    $CeldaPieIzquierda = "style=`"padding:1px 6px;border-left:5px ridge gol" + `
                         "d;border-top:3px ridge gold;border-bottom:5px rid" + `
                         "ge gold;border-right:3px groove gold;`""
    $CeldaPieCentro = "style=`"padding:1px 6px;border-left:3px groove gold;" + `
                      "border-top:3px ridge gold;border-bottom:5px ridge go" + `
                      "ld;border-right:3px groove gold;`""
    $CeldaPieDerecha = "style=`"padding:1px 6px;border-left:3px groove gold" + `
                       ";border-top:3px ridge gold;border-bottom:5px ridge " + `
                       "gold;border-right:5px ridge gold;`""
    $FilaEncabezado = "style=`"background-color:sienna;color:lightgoldenrod" + `
                      "yellow;`""
    $FilaClara = "style=`"background-color:oldlace ;color:#000000;`""
    $FilaOscura = "style=`"background-color:wheat;color:#000000`""
    # En primer lugar creamos la tabla y sus encabezados
    $SyncHTML = "<table $Tabla>`r`n" + `
            "  <tr $FilaEncabezado>`r`n" + `
            "    <th $EncabezadoIzquierda>Servidor</th>`r`n" + `
            "    <th $EncabezadoCentro>Precedente</th>`r`n" + `
            "    <th $EncabezadoCentro>HoraInicio</th>`r`n" + `
            "    <th $EncabezadoCentro>HoraFinal</th>`r`n" + `
            "    <th $EncabezadoCentro>Minutos</th>`r`n" + `
            "    <th $EncabezadoCentro>TipoSinc</th>`r`n" + `
            "    <th $EncabezadoCentro>Resultado</th>`r`n" + `
            "    <th $EncabezadoDerecha>Error</th>`r`n" + `
            "  </tr>`r`n"
            
    $UpHTML = "<table $Tabla>`r`n" + `
            "  <tr $FilaEncabezado>`r`n" + `
            "    <th $EncabezadoIzquierda>Servidor</th>`r`n" + `
            "    <th $EncabezadoCentro>Actualizaciones</th>`r`n" + `
            "    <th $EncabezadoCentro>Aprovadas</th>`r`n" + `
            "    <th $EncabezadoCentro>CritNoAprov</th>`r`n" + `
            "    <th $EncabezadoCentro>Declinadas</th>`r`n" + `
            "    <th $EncabezadoCentro>Expiradas</th>`r`n" + `
            "    <th $EncabezadoCentro>NoAprovadas</th>`r`n" + `
            "    <th $EncabezadoCentro>Innecesarias</th>`r`n" + `
            "    <th $EncabezadoCentro>Necesarias</th>`r`n" + `
            "    <th $EncabezadoCentro>NoAprovadas</th>`r`n" + `
            "    <th $EncabezadoDerecha>Error</th>`r`n" + `
            "  </tr>`r`n"
            
    # Esta variable es un flag que nos indicará si la línea con la información
    # del servidor será oscura (True) o clara (False); nos permitirá que la
    # tabla sea bandeada.
    $Oscura = $false
    
    $i = 1
    
    # Recorremos los resultados quedándonos, por medio de Select-Object,
    # únicamente con las propiedades que nos interesan
    $Resultado | 
    Select-Object Servidor,Precedente,StartTime,EndTime,Tipo,Result,ErrorText | `
    ForEach{ `
        # El estilo de la línea actual va en función de si debe ser oscura o no.
        If($Oscura)
        {
            # Como el indicador marca oscura, establecemos el estilo oscuro e
            # invertimos el indicador
            $Estilo = $FilaOscura
            $Oscura = $false
        }
        Else
        {
            # Como el indicador no marca oscura, establecemos el estilo claro e
            # invertimos el indicador
            $Estilo = $FilaClara
            $Oscura = $true
        }
        If($i -lt $Resultado.Count)
        {
            $CeldaI = $CeldaIzquierda
            $CeldaC = $CeldaCentro
            $CeldaD = $CeldaDerecha
        }
        Else
        {
            $CeldaI = $CeldaPieIzquierda
            $CeldaC = $CeldaPieCentro
            $CeldaD = $CeldaPieDerecha
        }
        # Si no se produjo error, StartTime es de tipo Fecha/Hora
        If($_.StartTime -is [DateTime])
        {
            # Almacenamos como inicio la fecha hora en formato
            # "dd/MM/yyyy`nHH:mm:ss"
            $Inicio = $_.StartTime.ToString("dd/MM/yyyy`nHH:mm:ss")
        }
        # Se produjo error y por tanto en el campo StartTime no hay
        # una fecha, si no la cadena "N/A", que almacenaremos como $Inicio
        Else
        {
            $Inicio = $_.StartTime
        }
        # Lo mismo que hicimos con la fecha de inicio lo hacemos ahora con la
        # de final
        If($_.EndTime -is [DateTime])
        {
            $Fin = $_.EndTime.ToString("dd/MM/yyyy`nHH:mm:ss")
        }
        Else
        {
            $Fin = $_.EndTime
        }
        # En el caso de que tanto las fecha de inicio como la de fin sean
        # de tipo Fecha/Hora debemos calcular el número de minutos que ha
        # durado la sincronización; en caso de haberse producido error se
        # mostrará "N/A"
        If($_.StartTime -is [DateTime] -and $_.EndTime -is [DateTime])
        {
            $Minutos = "{0:n2}" -f ($_.EndTime - $_.StartTime).TotalMinutes
        }
        Else
        {
            $Minutos = "N/A"
        }
        
        # Si no se ha producido error, se mostrará como error "Ninguno"
        If([String]::IsNullOrEmpty($_.ErrorText))
        {
            $ErrorSync = "Ninguno"
        }
        # Se ha producido error, mostramos el error que se produjo
        Else
        {
            $ErrorSync = $_.ErrorText
        }
        # Montamos la línea con la información del servidor actual
        $SyncHTML = $SyncHTML + `
                "  <tr $Estilo>`r`n" + `
                "    <td $CeldaI>$($_.Servidor)</td>`r`n" + `
                "    <td $CeldaC>$($_.Precedente)</td>`r`n" + `
                "    <td $CeldaC>$Inicio</td>`r`n" + `
                "    <td $CeldaC>$Fin</td>`r`n" + `
                "    <td $CeldaC align=`"right`">$Minutos</td>`r`n" + `
                "    <td $CeldaC>$($_.Tipo)</td>`r`n" + `
                "    <td $CeldaC>$($_.Result)</td>`r`n" + `
                "    <td $CeldaD>$ErrorSync</td>`r`n" + `
                "  </tr>`r`n"    
    }
    # Una vez recorridos los servidores cerramos la tabla
    $SyncHTML = $SyncHTML + "</table>"
    
    # Agregamos al inicio del HTML el encabezado del mensaje
    $SyncHTML = "<p align=""justify"">" + $BodyHeader + "</p>`r`n" + $SyncHTML 
    
    # Por último, enviamos el mensaje de correo, indicando que se trata de HTML
    # (-BodyAsHtml), que la codificación es UTF-8 (-Encoding), destinatarios
    # (-To), remitente (-From), Asunto (-Subject) y servidor de correo con el
    # que realizar el envío (-SmtpServer)
    Send-MailMessage -Body $SyncHTML -BodyAsHtml -From $From -To $To `
                     -Subject $Subject -SmtpServer $SmtpServer `
                     -Encoding ([System.Text.Encoding]::UTF8)

<#
    .SYNOPSIS
        Envía un correo con la información sobre la última sincronización de los
servidores de WSUS.

    .DESCRIPTION
        Este Cmdlet permite enviar un correo con la información de los
resultados de la última sincronización de la plataforma de WSUS cuyo servidor
raíz es el recibido como parámetro. El correo enviado es en formato HTML.

    .PARAMETER  WsusServer
        Este parámetro establece el nombre del servidor WSUS al que se conectará
para obtener información de él y sus descendientes en la cadena.

    .PARAMETER  SmtpServer
        Este parámetro establece el servidor SMTP que se usará para enviar el
correo

    .PARAMETER  To
        Este parámetro establece el remitente como dirección de correo SMTP. Una
dirección de coreo SMTP puede ser de dos maneras:
        
            - NombreParaMostrar<correo> (Ejemplo "Pi, Filemón<fpi@tia.org>").
            - correo (Ejemplo "fpi@tia.org")

    .PARAMETER  From
        Este parámetro establece los destinatarios domo direcciones de de correo
SMTP.

    .PARAMETER  Subject
        Este parámetro establece el asunto del correo.

    .PARAMETER  BodyHeader
        Este parámetro establece el texto de introducción del cuerpo del
mensaje. Será incluído en un párrado (<p>) con la alineación justificada).

    .EXAMPLE    
        PS C:\> Send-WsusSynchronizationStatus -WsusServer "wsus.tia.org" `
                 -SmtpServer "smtp.tia.org" `
                 -To "Vicente, Superintendente<svicente@tia.org>", `
                     "Bacterio, Profesor<pbacterio@tia.org>" `
                 -From "Pi, Filemón<fpi@tia.org>" `
                 -Subject "Estado de WSUS $((Get-Date).ToString("yyyyMMdd"))" `
                 -BodyHeader "Asín están las cosas en WSUS."

    .INPUTS
        System.String,System.String[]

    .OUTPUTS
        None

    .NOTES
        12/2012 © Fernando Reyes López

    .LINK

http://freyes.svetlian.com

    .LINK

http://urpiano.wordpress.com

#>


}
About these ads

Deja un comentario

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

 
Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 39 seguidores

%d personas les gusta esto: