Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Windows Update Monitor
- Import-Module $env:SyncroModule -DisableNameChecking
- <# Todo: properly handle less common Win10 editions LTSB/LTSC & ESU
- https://learn.microsoft.com/en-us/windows/release-health/release-information
- Changes: - Split out $Win11MaxAge into editions
- - Handle last version of Windows 10 correctly (22H2 is 36 months)
- - Refactor code to be less redundant
- - Change alert message to use regular version instead of converted to numerical form
- - Properly handle 11 Enterprise/Edu/IoT Enterprise
- #>
- # Maximum age of builds you want to support in months
- [int]$Win10MaxAge = "18" # EOS for Home/Pro is 18 months except for 22H2 which we account for later
- [int]$Win11HomeProMaxAge = "24" # EOS for Home/Pro is 24 months
- [int]$Win11EntEduIoTMaxAge = "36" # EOS for Enterprise/Education/IoT Enterprise is 36 months
- # Number of days to consider an update recent
- $Recent = '50'
- # UTC Time Offset: check yours at https://www.timeanddate.com/time/difference/timezone/utc
- $Offset = '-6'
- # Check Windows version age
- $OSname = Get-CimInstance Win32_OperatingSystem | Select-Object -ExpandProperty Caption
- if ((Get-CimInstance Win32_OperatingSystem).Version -gt '10' -and $OSname -notlike '*Server*') {
- # Grab version (19041 and older do not have DisplayVersion so we grab ReleaseID)
- if ((Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").DisplayVersion) {
- $Version = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").DisplayVersion
- } else {
- $Version = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").ReleaseId
- }
- if ($OSname -match 'Windows 10') {
- # Adjustment for last version of Windows 10
- if ($Version -eq '22H2') {
- $MaxAge = 36
- } else { $MaxAge = $Win10MaxAge }
- }
- if ($OSname -match 'Windows 11 Home' -or $OSname -match 'Windows 11 Pro') {
- $MaxAge = $Win11HomeProMaxAge
- }
- if ($OSname -match 'Windows 11 Enterprise' -or $OSname -match 'Windows 11 Education' -or $OSname -match 'Windows 11 IoT Enterprise') {
- $MaxAge = $Win11EntEduIoTMaxAge
- }
- # Convert current date to comparable format and subtract $MaxAge
- $CurrentDate = (Get-Date).AddMonths(-$MaxAge).ToString("yyMM")
- # Convert $Version to numerical format and subtract $CurrentDate
- $VersionNumerical = ($Version).replace('H1', '05').replace('H2', '10')
- $Diff = $VersionNumerical - $CurrentDate
- if ($Diff -lt '0') {
- Write-Host "$OSname $Version is over $MaxAge months old, needs upgrading"`n
- Rmm-Alert -Category "Monitor - Windows Update" -Body "$OSname $Version is over $MaxAge months old, needs upgrading"
- exit 1
- } else {
- Write-Host "$OSname $Version is less than the max age of $MaxAge months"`n
- Close-Rmm-Alert -Category "Monitor - Windows Update"
- }
- } else {
- Write-Host "Unsupported OS: $OSname`nThis script only supports Windows 10 & 11, exiting..."
- }
- # Check for disabled services
- $DisabledServices = Get-Service WUAUServ, BITS, CryptSvc, RPCSS, EventLog | Where-Object -Property 'StartType' -eq 'Disabled'
- if ($DisabledServices) {
- "Disabled Services:"
- $DisabledServices
- Rmm-Alert -Category "Monitor - Windows Update" -Body "Disabled Services: $DisabledService"
- exit 1
- } else {
- Close-Rmm-Alert -Category "Monitor - Windows Update"
- }
- # If the Microsoft Update service is not enabled, enable it.
- $UpdateService = New-Object -ComObject Microsoft.Update.ServiceManager
- $MicrosoftUpdateService = $UpdateService.Services | Where-Object { $_.ServiceId -eq '7971f918-a847-4430-9279-4a52d1efe18d' }
- if (!$MicrosoftUpdateService) {
- $UpdateService.AddService2('7971f918-a847-4430-9279-4a52d1efe18d', 7, '')
- }
- # Check if recent updates are installed
- $WindowsUpdateObject = New-Object -ComObject Microsoft.Update.AutoUpdate
- $SearchSuccessDate = $WindowsUpdateObject.Results | Select-Object LastSearchSuccessDate
- $SSDLastDate = ([datetime]$SearchSuccessDate.LastSearchSuccessDate).AddHours($Offset)
- $SSDDays = (New-TimeSpan -Start $SSDLastDate -End (Get-Date) | Select-Object Days).Days
- Write-Host 'Last Search Success:' $SSDLastDate "($SSDDays days ago)"`n
- $InstallSuccessDate = $windowsUpdateObject.Results | Select-Object LastInstallationSuccessDate
- $ISDLastDate = ([datetime]$InstallSuccessDate.LastInstallationSuccessDate).AddHours($Offset)
- $ISDDays = (New-TimeSpan -Start $ISDLastDate -End (Get-Date) | Select-Object Days).Days
- Write-Host 'Last Installation Success:' $ISDLastDate "($ISDDays days ago)"`n
- $Searcher = (New-Object -ComObject 'Microsoft.Update.Session').CreateUpdateSearcher()
- $HistoryCount = $Searcher.GetTotalHistoryCount()
- if ($HistoryCount -gt 0) {
- $xx = $Searcher.QueryHistory(0, $HistoryCount) | Where-Object { $_.Operation -like 1 -and $_.ResultCode -match '[123]' } | Select-Object Title
- }
- $LastMonth = (Get-Date).AddMonths(-1).ToString("yyyy-MM")
- $ThisMonth = (Get-Date).ToString("yyyy-MM")
- $xx = $xx | Where-Object { $_ -match "($LastMonth|$ThisMonth) (Security Monthly Quality Rollup for Windows|Cumulative Update for Windows)" -or $_ -match "Feature update" }
- if (!$xx -and $ISDDays -gt $Recent) {
- Write-Output "WARNING - No recent rollup/cumulative/feature update detected"
- Write-Output "Last updates:"
- $xx | Select-Object -ExpandProperty Title -First 1
- Rmm-Alert -Category "Monitor - Windows Update" -Body "WARNING - No recent rollup/cumulative/feature update detected"
- exit 1
- } else {
- Write-Output "Recent rollup or cumulative update detected:"
- $xx | Select-Object -ExpandProperty Title -First 1
- Close-Rmm-Alert -Category "Monitor - Windows Update"
- }
Advertisement
Add Comment
Please, Sign In to add comment