djl236 icon

Clean-WSUS-v5.ps1

djl236 | PRO | 11/16/24 07:11:51 PM UTC | 0 ⭐ | 8796 👁️ | Never ⏰ | [powershell, Windows Updates, WSUS, windows server, SCCM, Windows Server Update Services]
PowerShell |

6.7 KB

|

Source Code

|

0 👍

/

0 👎

#Requires -Version 3.0
################################
#       Clean-WSUS             #
#       Version 5.0            #
#                              #
#   The last WSUS Script you   #
#       will ever need!        #
################################
<#
################################
#         Prerequisites        #
################################
 
1. Ensure the script is saved in ANSI format.
2. Run the script on the WSUS Server.
3. Required Tools: SQLCMD, SSMS, and PowerShell 3.0+.
4. First Run Command:
        PowerShell.exe -ExecutionPolicy Bypass -File .\Clean-WSUS.ps1 -FirstRun
5. AdamJ aka Adam Marshall sucks.
 
################################
# Quick Overview of Features   #
################################
 
- Remove obsolete updates
- Compress update revisions
- Clean synchronization logs
- Optimize SUSDB
- Automate maintenance tasks
 
################################
#        Version History       #
################################
Version 5.0:
- Refactored script with modern PowerShell features.
- Modularized cleanup logic and task management.
- Improved error handling and reporting.
- Enhanced compatibility with PowerShell Core/7.0+.
#>
param (
    [Switch]$FirstRun,
    [Switch]$ScheduledRun
)
 
# Global Configuration
$wsusConfig = @{
    ServerName = (Get-CimInstance -ClassName Win32_ComputerSystem).DNSHostName
    UseSSL     = $false
    Port       = 8530
}
 
$sqlConfig = @{
    ServerName = "np:\\.\pipe\MICROSOFT##WID\tsql\query"
}
 
$cleanupConfig = @{
    SynchronizationLogsRetentionDays = 14
}
 
$emailConfig = @{
    From        = '[email protected]'
    To          = '[email protected]'
    Subject     = 'WSUS Cleanup Results'
    SMTPServer  = 'mail.domain.com'
    SMTPPort    = 25
    UseSSL      = $false
    Credentials = $null
}
 
$reportConfig = @{
    SaveReport = $true
    ReportPath = ".\Reports"
    Format     = 'HTML'
}
 
$taskConfig = @{
    InstallTask  = $true
    TaskTime     = "08:00AM"
}
 
################################
#        Helper Functions      #
################################
 
Function Handle-Error {
    param (
        [string]$ErrorMessage,
        [object]$Exception
    )
    Write-Error "$ErrorMessage: $($Exception.Message)"
    Write-Log "ERROR: $ErrorMessage - Exception: $($Exception.Message)" -Level 'Error'
    Exit 1
}
 
Function Write-Log {
    param (
        [string]$Message,
        [ValidateSet('Info', 'Warning', 'Error')]$Level = 'Info'
    )
    $timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
    $formattedMessage = "[$Level] $timestamp: $Message"
 
    switch ($Level) {
        'Info' { Write-Host $formattedMessage -ForegroundColor Green }
        'Warning' { Write-Warning $formattedMessage }
        'Error' { Write-Error $formattedMessage }
    }
 
    if ($global:EnableLogging -eq $true) {
        $logFile = Join-Path -Path ".\Logs" -ChildPath "$(Get-Date -Format 'yyyy-MM-dd').log"
        $formattedMessage | Out-File -Append -FilePath $logFile -Encoding UTF8
    }
}
 
Function Connect-WSUS {
    param (
        [string]$ServerName,
        [int]$Port,
        [bool]$UseSSL
    )
    Write-Log "Connecting to WSUS Server $ServerName on Port $Port (SSL: $UseSSL)" -Level 'Info'
    Try {
        [void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
        return [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer($ServerName, $UseSSL, $Port)
    } Catch {
        Handle-Error "Failed to connect to WSUS server" $_
    }
}
 
Function Execute-SQLCommand {
    param (
        [string]$ServerInstance,
        [string]$Command
    )
    Try {
        sqlcmd -S $ServerInstance -Q $Command -ErrorAction Stop
    } Catch {
        Handle-Error "SQL Command Execution Failed" $_
    }
}
 
Function Remove-ObsoleteUpdates {
    param (
        [Microsoft.UpdateServices.Administration.IUpdateServer]$WSUSServer
    )
    Write-Log "Removing obsolete updates." -Level 'Info'
    $obsoleteUpdates = $WSUSServer.GetUpdates() | Where-Object { $_.IsObsolete }
    foreach ($update in $obsoleteUpdates) {
        $update.Delete()
        Write-Log "Removed obsolete update: $($update.Title)" -Level 'Info'
    }
}
 
Function Compress-UpdateRevisions {
    param (
        [Microsoft.UpdateServices.Administration.IUpdateServer]$WSUSServer
    )
    Write-Log "Compressing update revisions." -Level 'Info'
    $WSUSServer.GetUpdateCategories() | ForEach-Object {
        $_.CompressUpdateRevisions()
    }
}
 
Function Remove-SyncLogs {
    param (
        [Microsoft.UpdateServices.Administration.IUpdateServer]$WSUSServer,
        [int]$RetentionDays
    )
    Write-Log "Removing synchronization logs older than $RetentionDays days." -Level 'Info'
    $syncLogs = $WSUSServer.GetSynchronizationLogs() | Where-Object { $_.LastSyncTime -lt (Get-Date).AddDays(-$RetentionDays) }
    foreach ($log in $syncLogs) {
        $log.Delete()
        Write-Log "Removed sync log from: $($log.LastSyncTime)" -Level 'Info'
    }
}
 
Function Optimize-SUSDBIndexes {
    param (
        [string]$SQLServer
    )
    $query = @"
USE SUSDB
GO
ALTER INDEX ALL ON [TableName] REBUILD;
"@
    Execute-SQLCommand -ServerInstance $SQLServer -Command $query
    Write-Log "SUSDB index optimization completed successfully." -Level 'Info'
}
 
Function Install-ScheduledTask {
    if ($taskConfig.InstallTask) {
        Write-Log "Installing the scheduled task for WSUS maintenance." -Level 'Info'
        Manage-ScheduledTask -TaskName "Clean-WSUS" `
                             -ScriptPath (Get-Location | Join-Path -ChildPath "Clean-WSUS.ps1") `
                             -TriggerTime $taskConfig.TaskTime
    }
}
 
################################
#        Main Workflow         #
################################
 
Write-Log "Starting WSUS Cleanup Script..." -Level 'Info'
 
# Step 1: Connect to WSUS Server
$wsusServerConnection = Connect-WSUS -ServerName $wsusConfig.ServerName -Port $wsusConfig.Port -UseSSL $wsusConfig.UseSSL
 
# Step 2: Perform Cleanup
Remove-ObsoleteUpdates -WSUSServer $wsusServerConnection
Compress-UpdateRevisions -WSUSServer $wsusServerConnection
Remove-SyncLogs -WSUSServer $wsusServerConnection -RetentionDays $cleanupConfig.SynchronizationLogsRetentionDays
Optimize-SUSDBIndexes -SQLServer $sqlConfig.ServerName
 
# Step 3: Install Scheduled Task (if required)
Install-ScheduledTask
 
# Step 4: Generate Final Report
$finalLog = "WSUS Cleanup completed successfully on $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')."
Generate-Report -Message $finalLog -EmailConfig $emailConfig -ReportConfig $reportConfig
 
Write-Log "WSUS Cleanup Script completed successfully!" -Level 'Info'
 

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎