Advertisement
Guest User

Find Most Recent Windows CU Installed

a guest
Apr 2nd, 2024
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function Find-WindowsUpdateLastCUInstalled {
  2.     [CmdletBinding()]
  3.     param (
  4.         [Parameter(Mandatory = $false)]
  5.         [Switch]
  6.         $ByHistory
  7.     )
  8.  
  9.     begin {
  10.         $OSVer = (Get-Item C:\Windows\System32\ntoskrnl.exe).VersionInfo.FileVersionRaw
  11.         if ($OSVer.Major -ne 10 -or $OSVer.Minor -ne 0)
  12.         { throw [System.NotSupportedException]::new("OS version must be 10.0.x.x") }
  13.     }process {
  14.         if ($ByHistory) {
  15.             Write-PSFMessage -Level Warning -Message "This method is less reliable as uninstallations are not included in the history."
  16.    
  17.             $UpdateSession = (New-Object -ComObject 'Microsoft.Update.Session')
  18.             $UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
  19.             $UpdateHistory = $UpdateSearcher.QueryHistory(0, $UpdateSearcher.GetTotalHistoryCount())
  20.             $LastCU = $UpdateHistory | Where-Object {
  21.                 $_.Title -match "\d{4}-\d{2}\sCumulative Update for (?:Windows|Microsoft\sserver\soperating\ssystem)" -and $_.ResultCode -eq 2 } |
  22.             Sort-Object Date -Descending | Select-Object -First 1
  23.             if ($LastCU) {
  24.                 [void]($LastCU.Title -match "(?<Series>\d{4}-\d{2})\sCumulative Update for (?:Windows|Microsoft\sserver\soperating\ssystem)")
  25.                 $LastCU | Add-Member -NotePropertyName "Series" -NotePropertyValue ([DateTime]::Parse($Matches.Series)) -Force
  26.        
  27.                 return $LastCU
  28.             }
  29.         }
  30.         else {
  31.             if (-not (Test-Path -Path "$PSScriptRoot\BuildTable.json")) {
  32.                 Write-PSFMessage -Level Error -Message "Please run 'Update-WindowsUpdateCUBuildTable' before running this command. Please note, you will need an Internet connection for this command."
  33.                 return
  34.             }
  35.             elseif (((Get-Date) - (Get-Item -Path "$PSScriptRoot\BuildTable.json").LastWriteTime).TotalDays -ge 30) {
  36.                 Write-PSFMessage -Level Warning -Message "It has been at least 30 days since the build table was last updated. It is recommended to run 'Update-WindowsUpdateCUBuildTable' (requires an Internet connection)."
  37.             }
  38.    
  39.             try
  40.             { $BuildTable = Get-Content -Path "$PSScriptRoot\BuildTable.json" -Raw | ConvertFrom-Json -ErrorAction Stop }
  41.             catch
  42.             { Write-PSFMessage -Level Critical -Message "The build table seems to be corrupted. Please run 'Update-WindowsUpdateCUBuildTable' (requires an Internet connection)."; return }
  43.    
  44.             if (-not ($BuildTable | Get-Member -MemberType NoteProperty -Name "Build"))
  45.             { Write-PSFMessage -Level Critical -Message "The build table seems to be corrupted. Please run 'Update-WindowsUpdateCUBuildTable' (requires an Internet connection)."; return }
  46.    
  47.             return $BuildTable | Where-Object { $_.Build.Major -eq $OSVer.Major -and $_.Build.Minor -eq $OSVer.Minor -and $_.Build.Revision -eq $OSVer.Revision } | Select-Object -First 1
  48.         }
  49.     }
  50. }
  51.  
  52. function Update-WindowsUpdateCUBuildTable {
  53.     [CmdletBinding()]
  54.     param ()
  55.  
  56.     begin {
  57.         $WIN_MAJORMINOR = "10.0"
  58.         $WIN_KB_URLS = @(
  59.             "https://support.microsoft.com/en-us/help/5018682", # Windows 10, Server 2016, Server 2019
  60.             "https://support.microsoft.com/en-us/help/5031682" # Windows 11
  61.             "https://support.microsoft.com/en-us/help/5005454" # Server 2022
  62.         )
  63.         $NAVTAB_REGEX = "(?i)((?:(?:Jan|Feb|Mar|Apr|May|June|July|Aug|Sept|Oct|Nov|Dec)\.{0,1}|(?:January|February|March|April|May|June|July|August|September|October|November|December))\s+\d{1,2},\s+\d{4}).+(KB\d+){1}.+(?:OS Build(?:s){0,1}\s((?:\d+\.\d+).*))\)(?:\s(.+)<)*"
  64.        
  65.         $BuildTable = @()
  66.     }process {
  67.         $WIN_KB_URLS | ForEach-Object {
  68.             try
  69.             { $htmlSrc = Invoke-RestMethod -Uri $_ -UseBasicParsing -ErrorAction Stop }
  70.             catch
  71.             { Write-PSFMessage -Level Critical -Message $Error[0]; return }
  72.  
  73.             [Regex]::Matches($htmlSrc, $NAVTAB_REGEX) | ForEach-Object {
  74.                 $g = $_.Groups
  75.                 ($g[3] -replace "[^0-9. ]", "").Split(" ") | Where-Object { $_ } | ForEach-Object {
  76.                     $BuildTable += [PSCustomObject]@{
  77.                         KB         = $g[2].Value
  78.                         DateStamp  = [DateTime]::Parse($g[1].Value)
  79.                         Build      = [Version]"$WIN_MAJORMINOR.$_"
  80.                         Descriptor = $g[4].Value
  81.                     }
  82.                 }
  83.             }
  84.         }
  85.  
  86.         $BuildTable | ConvertTo-Json | Out-File -FilePath "$PSScriptRoot\BuildTable.json"
  87.     }
  88. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement