powershell Reporte de Actualizaciones WSUS
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了powershell Reporte de Actualizaciones WSUS相关的知识,希望对你有一定的参考价值。
<#
WSUS Report
** Requires WSUS Administrator Console Installed or UpdateServices Module available **
TO DO:
- SUSDB Size
- Computers in Active Directory but not in WSUS (OPTIONAL)
#>
#region User Specified WSUS Information
$WSUSServer = 'XXXX'
#Accepted values are "80","443","8530" and "8531"
$Port = 8530
$UseSSL = $False
#Specify when a computer is considered stale
$DaysComputerStale = 50
#Send email of report
[bool]$SendEmail = $FALSE
#Display HTML file
[bool]$ShowFile = $FALSE
#endregion User Specified WSUS Information
#region User Specified Email Information
$EmailParams = @{
To = 'user@domain.local'
From = 'WSUSReport@domain.local'
Subject = "$WSUSServer WSUS Report"
SMTPServer = 'exchange.domain.local'
BodyAsHtml = $True
}
#endregion User Specified Email Information
#region Helper Functions
Function Set-AlternatingCSSClass {
[CmdletBinding()]
param(
[Parameter(Mandatory=$True,ValueFromPipeline=$True)]
[string]$HTMLFragment,
[Parameter(Mandatory=$True)]
[string]$CSSEvenClass,
[Parameter(Mandatory=$True)]
[string]$CssOddClass
)
[xml]$xml = $HTMLFragment
$table = $xml.SelectSingleNode('table')
$classname = $CSSOddClass
foreach ($tr in $table.tr) {
if ($classname -eq $CSSEvenClass) {
$classname = $CssOddClass
} else {
$classname = $CSSEvenClass
}
$class = $xml.CreateAttribute('class')
$class.value = $classname
$tr.attributes.append($class) | Out-null
}
$xml.innerxml | out-string
}
Function Convert-Size {
[cmdletbinding()]
Param (
[parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
[Alias("Length")]
[int64]$Size
)
Begin {
If (-Not $ConvertSize) {
Write-Verbose ("Creating signature from Win32API")
$Signature = @"
[DllImport("Shlwapi.dll", CharSet = CharSet.Auto)]
public static extern long StrFormatByteSize( long fileSize, System.Text.StringBuilder buffer, int bufferSize );
"@
$Global:ConvertSize = Add-Type -Name SizeConverter -MemberDefinition $Signature -PassThru
}
Write-Verbose ("Building buffer for string")
$stringBuilder = New-Object Text.StringBuilder 1024
}
Process {
Write-Verbose ("Converting {0} to upper most size" -f $Size)
$ConvertSize::StrFormatByteSize( $Size, $stringBuilder, $stringBuilder.Capacity ) | Out-Null
$stringBuilder.ToString()
}
}
#endregion Helper Functions
#region Load WSUS Required Assembly
If (-Not (Get-Module -ListAvailable -Name UpdateServices)) {
#Add-Type "$Env:ProgramFiles\Update Services\Api\Microsoft.UpdateServices.Administration.dll"
$Null = [reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
} Else {
Import-Module -Name UpdateServices
}
#endregion Load WSUS Required Assembly
#region CSS Layout
$head=@"
<style>
h1 {
text-align:center;
border-bottom:1px solid #666666;
color:#009933;
}
TABLE {
TABLE-LAYOUT: auto;
FONT-SIZE: 100%;
WIDTH: 100%
}
* {
margin:0
}
.pageholder {
margin: 0px auto;
}
td {
VERTICAL-ALIGN: TOP;
FONT-FAMILY: Tahoma
}
th {
VERTICAL-ALIGN: TOP;
COLOR: #018AC0;
TEXT-ALIGN: left;
background-color:DarkGrey;
color:Black;
}
body {
text-align:left;
font-smoothing:always;
width:100%;
}
.odd { background-color:#ffffff; }
.even { background-color:#dddddd; }
</style>
"@
#endregion CSS Layout
#region Initial WSUS Connection
$ErrorActionPreference = 'Stop'
Try {
$Wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer($WSUSServer,$UseSSL,$Port)
} Catch {
Write-warning "$($WSUSServer)<$($Port)>: $($_)"
Break
}
$ErrorActionPreference = 'Continue'
#endregion Initial WSUS Connection
#region Pre-Stage -- Used in more than one location
$htmlFragment = ''
$WSUSConfig = $Wsus.GetConfiguration()
$WSUSStats = $Wsus.GetStatus()
$TargetGroups = $Wsus.GetComputerTargetGroups()
$EmptyTargetGroups = $TargetGroups | Where {
$_.GetComputerTargets().Count -eq 0 -AND $_.Name -ne 'Unassigned Computers'
}
#Stale Computers
$computerscope = New-Object Microsoft.UpdateServices.Administration.ComputerTargetScope
$computerscope.ToLastReportedStatusTime = (Get-Date).AddDays(-$DaysComputerStale)
$StaleComputers = $wsus.GetComputerTargets($computerscope) | ForEach {
[pscustomobject]@{
"Nombre del Equipo" = $_.FullDomainName
IP = $_.IPAddress
"Ultimo Contacto" = $_.LastReportedStatusTime
"Ultima Sincronizacion" = $_.LastSyncTime
Grupo = ($_.GetComputerTargetGroups() | Where-Object {$_.Name -ne "Todos los Equipos"} | Select -Expand Name) -join ', '
}
}
#Pending Reboots
$updateScope = New-Object Microsoft.UpdateServices.Administration.UpdateScope
$updateScope.IncludedInstallationStates = 'InstalledPendingReboot'
$computerScope = New-Object Microsoft.UpdateServices.Administration.ComputerTargetScope
$computerScope.IncludedInstallationStates = 'InstalledPendingReboot'
$GroupRebootHash=@{}
$ComputerPendingReboot = $wsus.GetComputerTargets($computerScope) | ForEach {
$Update = ($_.GetUpdateInstallationInfoPerUpdate($updateScope) | ForEach {
$Update = $_.GetUpdate()
$Update.title
}) -join ', '
If ($Update) {
$TempTargetGroups = ($_.GetComputerTargetGroups() | Where-Object {$_.Name -ne "Todos los Equipos"} | Select -Expand Name) -join ', '
$TempTargetGroups | ForEach {
$GroupRebootHash[$_]++
}
[pscustomobject] @{
"Nombre del equipo" = $_.FullDomainName
IP = $_.IPAddress
Grupo = $TempTargetGroups -join ', '
#Updates = $Update
}
}
} | Sort Computername
#NotInstalled
$updateScope = New-Object Microsoft.UpdateServices.Administration.UpdateScope
$updateScope.IncludedInstallationStates = 'NotInstalled'
$computerScope = New-Object Microsoft.UpdateServices.Administration.ComputerTargetScope
$computerScope.IncludedInstallationStates = 'NotInstalled'
$GroupNotInstalledHash=@{}
$ComputerHash = @{}
$UpdateHash = @{}
$ComputerNotInstall = $wsus.GetComputerTargets($computerScope) | ForEach {
$Computername = $_.FullDomainName
$Update = ($_.GetUpdateInstallationInfoPerUpdate($updateScope) | ForEach {
$Update = $_.GetUpdate()
$Update.title
$ComputerHash[$Computername] += ,$Update.title
$UpdateHash[$Update.title] += ,$Computername
}) -join ', '
If ($Update) {
$TempTargetGroups = ($_.GetComputerTargetGroups() | Where-Object {$_.Name -ne "Todos los Equipos"} | Select -Expand Name) -join ', '
$TempTargetGroups | ForEach {
$GroupNotInstalledHash[$_]++
}
[pscustomobject] @{
"Nombre del Equipo" = $_.FullDomainName
IP = $_.IPAddress
Grupo = $TempTargetGroups -join ', '
Actualizaciones = $Update
}
}
} | Sort Computername
#Failed Installations
$updateScope = New-Object Microsoft.UpdateServices.Administration.UpdateScope
$updateScope.IncludedInstallationStates = 'Failed'
$computerScope = New-Object Microsoft.UpdateServices.Administration.ComputerTargetScope
$computerScope.IncludedInstallationStates = 'Failed'
$GroupFailHash=@{}
$ComputerHash = @{}
$UpdateHash = @{}
$ComputerFailInstall = $wsus.GetComputerTargets($computerScope) | ForEach {
$Computername = $_.FullDomainName
$Update = ($_.GetUpdateInstallationInfoPerUpdate($updateScope) | ForEach {
$Update = $_.GetUpdate()
$Update.title
$ComputerHash[$Computername] += ,$Update.title
$UpdateHash[$Update.title] += ,$Computername
}) -join ', '
If ($Update) {
$TempTargetGroups = ($_.GetComputerTargetGroups() | Where-Object {$_.Name -ne "Todos los Equipos"} | Select -Expand Name) -join ', '
$TempTargetGroups | ForEach {
$GroupFailHash[$_]++
}
[pscustomobject] @{
"Nombre del Equipo" = $_.FullDomainName
IP = $_.IPAddress
Grupo = $TempTargetGroups -join ', '
Actualizaciones = $Update
}
}
} | Sort Computername
#endregion Pre-Stage -- Used in more than one location
#region WSUS SERVER INFORMATION
$Pre = @"
<div style='margin: 0px auto; BACKGROUND-COLOR:Blue;Color:White;font-weight:bold;FONT-SIZE: 16pt;'>
Informacion del servidor WSUS
</div>
"@
#region WSUS Version
$WSUSVersion = [pscustomobject]@{
Servidor = $WSUS.ServerName
Version = $Wsus.Version
Puerto = $Wsus.PortNumber
"Protocolo de Version del Servidor" = $Wsus.ServerProtocolVersion
}
$Pre += @"
<div style='margin: 0px auto; BACKGROUND-COLOR:LightBlue;Color:Black;font-weight:bold;FONT-SIZE: 14pt;'>
Informacion del Servicio WSUS
</div>
"@
$Body = $WSUSVersion | ConvertTo-Html -Fragment | Out-String | Set-AlternatingCSSClass -CSSEvenClass 'even' -CssOddClass 'odd'
$Post = "<br>"
$htmlFragment += $Pre,$Body,$Post
#endregion WSUS Version
#region WSUS Server Content
$drive = $WSUSConfig.LocalContentCachePath.Substring(0,2)
$Data = Get-CIMInstance -ComputerName $WSUSServer -ClassName Win32_LogicalDisk -Filter "DeviceID='$drive'"
$UsedSpace = $data.Size - $data.Freespace
$PercentFree = "{0:P}" -f ($Data.Freespace / $Data.Size)
$Pre = @"
<div style='margin: 0px auto; BACKGROUND-COLOR:LightBlue;Color:Black;font-weight:bold;FONT-SIZE: 14pt;'>
Informacion del almacenamiento de WSUS
</div>
"@
$WSUSDrive = [pscustomobject]@{
"Ruta de archivos" = $WSUSConfig.LocalContentCachePath
"Espacio total" = $data.Size | Convert-Size
"Espacio Utilizado" = $UsedSpace | Convert-Size
"Espacio Libre" = $Data.freespace | Convert-Size
"% libre" = $PercentFree
}
$Body = $WSUSDrive | ConvertTo-Html -Fragment | Out-String | Set-AlternatingCSSClass -CSSEvenClass 'even' -CssOddClass 'odd'
$Post = "<br>"
$htmlFragment += $Pre,$Body,$Post
#endregion WSUS Server Content
#region Last Synchronization
$synch = $wsus.GetSubscription()
$SynchHistory = $Synch.GetSynchronizationHistory()[0]
$WSUSSynch = [pscustomobject]@{
Automatica = $synch.SynchronizeAutomatically
"Hora Programada" = $synch.SynchronizeAutomaticallyTimeOfDay
"Ultima Sincronizacion" = $synch.LastSynchronizationTime
Resultado = $SynchHistory.Result
}
If ($SynchHistory.Result -eq 'Failed') {
$WSUSSynch = $WSUSSynch | Add-Member -MemberType NoteProperty -Name ErrorType -Value $SynchHistory.Error -PassThru |
Add-Member -MemberType NoteProperty -Name ErrorText -Value $SynchHistory.ErrorText -PassThru
}
$Pre = @"
<div style='margin: 0px auto; BACKGROUND-COLOR:LightBlue;Color:Black;font-weight:bold;FONT-SIZE: 14pt;'>
Ultima sincronizacion del servidor
</div>
"@
$Body = $WSUSSynch | ConvertTo-Html -Fragment | Out-String | Set-AlternatingCSSClass -CSSEvenClass 'even' -CssOddClass 'odd'
$Post = "<br>"
$htmlFragment += $Pre,$Body,$Post
#endregion Last Synchronization
#endregion WSUS SERVER INFORMATION
#region CLIENT INFORMATION
$Pre = @"
<div style='margin: 0px auto; BACKGROUND-COLOR:Blue;Color:White;font-weight:bold;FONT-SIZE: 16pt;'>
Informacion de Equipos
</div>
"@
#region Computer Statistics
$WSUSComputerStats = [pscustomobject]@{
"Total equipos" = [int]$WSUSStats.ComputerTargetCount
"Stale($DaysComputerStale Days)" = ($StaleComputers | Measure-Object).count
"Equipos pendientes de actualizar" = [int]$WSUSStats.ComputerTargetsNeedingUpdatesCount
"Instalaciones con errores" = [int]$WSUSStats.ComputerTargetsWithUpdateErrorsCount
"Pendientes de reiniciar" = ($ComputerPendingReboot | Measure-Object).Count
}
$Pre += @"
<div style='margin: 0px auto; BACKGROUND-COLOR:LightBlue;Color:Black;font-weight:bold;FONT-SIZE: 14pt;'>
Estadisticas de Equipos
</div>
"@
$Body = $WSUSComputerStats | ConvertTo-Html -Fragment | Out-String | Set-AlternatingCSSClass -CSSEvenClass 'even' -CssOddClass 'odd'
$Post = "<br>"
$htmlFragment += $Pre,$Body,$Post
#endregion Computer Statistics
#region Operating System
$Pre = @"
<div style='margin: 0px auto; BACKGROUND-COLOR:LightBlue;Color:Black;font-weight:bold;FONT-SIZE: 14pt;'>
Contador de equipos por Sistema Operativo
</div>
"@
$Body = $wsus.GetComputerTargets() | Group OSDescription |
Select @{L='Sistema Operativo';E={$_.Name}}, Count |
ConvertTo-Html -Fragment | Out-String | Set-AlternatingCSSClass -CSSEvenClass 'even' -CssOddClass 'Odd'
$Post = "<br>"
$htmlFragment += $Pre,$Body,$Post
#endregion Operating System
#region Stale Computers
$Pre = @"
<div style='margin: 0px auto; BACKGROUND-COLOR:LightBlue;Color:Black;font-weight:bold;FONT-SIZE: 14pt;'>
Equipos sin comunicacion ($DaysComputerStale dias)
</div>
"@
$Body = $StaleComputers | ConvertTo-Html -Fragment | Out-String | Set-AlternatingCSSClass -CSSEvenClass 'even' -CssOddClass 'odd'
$Post = "<br>"
$htmlFragment += $Pre,$Body,$Post
#endregion Stale Computers
#region Unassigned Computers
$Unassigned = ($TargetGroups | Where {
$_.Name -eq 'Equipos sin Asignar'
}).GetComputerTargets() | ForEach {
[pscustomobject]@{
Equipo = $_.FullDomainName
"Sistema Operativo" = $_.OSDescription
IP = $_.IPAddress
"Ultimo Contacto" = $_.LastReportedStatusTime
"Ultima Sincronizacion" = $_.LastSyncTime
}
}
$Pre = @"
<div style='margin: 0px auto; BACKGROUND-COLOR:LightBlue;Color:Black;font-weight:bold;FONT-SIZE: 14pt;'>
Equipos sin Asignar
</div>
"@
$Body = $Unassigned | ConvertTo-Html -Fragment | Out-String | Set-AlternatingCSSClass -CSSEvenClass 'even' -CssOddClass 'odd'
$Post = "<br>"
$htmlFragment += $Pre,$Body,$Post
#endregion Unassigned Computers
#region Failed Update Install
$Pre = @"
<div style='margin: 0px auto; BACKGROUND-COLOR:LightBlue;Color:Black;font-weight:bold;FONT-SIZE: 14pt;'>
Equipos con errores de instalacion
</div>
"@
$Body = $ComputerFailInstall | ConvertTo-Html -Fragment | Out-String | Set-AlternatingCSSClass -CSSEvenClass 'even' -CssOddClass 'odd'
$Post = "<br>"
$htmlFragment += $Pre,$Body,$Post
#endregion Failed Update Install
#region Pending Reboot
$Pre = @"
<div style='margin: 0px auto; BACKGROUND-COLOR:LightBlue;Color:Black;font-weight:bold;FONT-SIZE: 14pt;'>
Equipos pendientes de reiniciar
</div>
"@
$Body = $ComputerPendingReboot | ConvertTo-Html -Fragment | Out-String | Set-AlternatingCSSClass -CSSEvenClass 'even' -CssOddClass 'odd'
$Post = "<br>"
$htmlFragment += $Pre,$Body,$Post
#endregion Pending Reboot
#region Not Installed
$Pre = @"
<div style='margin: 0px auto; BACKGROUND-COLOR:LightBlue;Color:Black;font-weight:bold;FONT-SIZE: 14pt;'>
Equipos con actualizaciones pendientes
</div>
"@
$Body = $ComputerNotInstall | ConvertTo-Html -Fragment | Out-String | Set-AlternatingCSSClass -CSSEvenClass 'even' -CssOddClass 'odd'
$Post = "<br>"
$htmlFragment += $Pre,$Body,$Post
#endregion Not Installed
#endregion CLIENT INFORMATION
#region UPDATE INFORMATION
$Pre = @"
<div style='margin: 0px auto; BACKGROUND-COLOR:Blue;Color:White;font-weight:bold;FONT-SIZE: 16pt;'>
Informacion de Actualizaciones
</div>
"@
#region Update Statistics
$WSUSUpdateStats = [pscustomobject]@{
Totales = [int]$WSUSStats.UpdateCount
Necesarias = [int]$WSUSStats.UpdatesNeededByComputersCount
Aprobadas = [int]$WSUSStats.ApprovedUpdateCount
Rechazadas = [int]$WSUSStats.DeclinedUpdateCount
"Necesitan Ficheros" = [int]$WSUSStats.ExpiredUpdateCount
"Pendientes de Aprobar" = [int]$WSUSStats.NotApprovedUpdateCount
}
$Pre += @"
<div style='margin: 0px auto; BACKGROUND-COLOR:LightBlue;Color:Black;font-weight:bold;FONT-SIZE: 14pt;'>
Estadisticas de Actualizaciones
</div>
"@
$Body = $WSUSUpdateStats | ConvertTo-Html -Fragment | Out-String | Set-AlternatingCSSClass -CSSEvenClass 'even' -CssOddClass 'odd'
$Post = "<br>"
$htmlFragment += $Pre,$Body,$Post
#endregion Update Statistics
#region Failed Update Installations
$FailedUpdateInstall = $UpdateHash.GetEnumerator() | ForEach {
[pscustomobject]@{
Actualizacion = $_.Name
"Nombre del Equipo" = ($_.Value) -join ', '
}
}
$Pre = @"
<div style='margin: 0px auto; BACKGROUND-COLOR:LightBlue;Color:Black;font-weight:bold;FONT-SIZE: 14pt;'>
Instalaciones fallidas por actualizacion
</div>
"@
$Body = $FailedUpdateInstall | ConvertTo-Html -Fragment | Out-String | Set-AlternatingCSSClass -CSSEvenClass 'even' -CssOddClass 'odd'
$Post = "<br>"
$htmlFragment += $Pre,$Body,$Post
#endregion Failed Update Installations
#endregion UPDATE INFORMATION
#region Compile HTML Report
$HTMLParams = @{
Head = $Head
Title = "WSUS Report for $WSUSServer"
PreContent = "<H1><font color='white'>Please view in html!</font><br>$WSUSServer WSUS Report</H1>"
PostContent = "$($htmlFragment)<i>Report generated on $((Get-Date).ToString())</i>"
}
$Report = ConvertTo-Html @HTMLParams | Out-File -FilePath c:\WSUS.html
#endregion Compile HTML Report
If ($ShowFile) {
$Report | Out-File WSUSReport.html
Invoke-Item WSUSReport.html
}
#region Send Email
If ($SendEmail) {
$EmailParams.Body = $Report
Send-MailMessage @EmailParams
}
#endregion Send Email
以上是关于powershell Reporte de Actualizaciones WSUS的主要内容,如果未能解决你的问题,请参考以下文章
powershell 抑制de lignesvidesaprèsunsplit
powershell Listado de usuarios en VPN