├── .github └── FUNDING.yml ├── CI └── WindowOSBuild.Tests.ps1 ├── LICENCE ├── Private └── Import-HtmlAgilityPack.ps1 ├── Public ├── Get-CurrentOSBuild.ps1 └── Get-LatestOSBuild.ps1 ├── README.md ├── WindowsOSBuild.png ├── WindowsOSBuild.psd1 ├── WindowsOSBuild.psm1 ├── appveyor.yml └── lib ├── HtmlAgilityPack-1.12.0.0-net40-client.dll ├── HtmlAgilityPack-1.12.0.0-netstandard2.dll └── HtmlAgilityPack.LICENCE /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [AshleyHow] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 15 | -------------------------------------------------------------------------------- /CI/WindowOSBuild.Tests.ps1: -------------------------------------------------------------------------------- 1 | 2 | 3 | BeforeAll { 4 | $Path = (Get-Item $PsScriptRoot).parent.FullName + "\WindowsOSBuild.psm1" 5 | . Import-Module -Name $Path -Verbose 6 | 7 | # Function to check if a string contains a valid date in YYYY-MM-DD format 8 | Function Find-ValidDate { 9 | Param ( 10 | [string]$InputString 11 | ) 12 | # Trim whitespace from the input string 13 | $InputString = $InputString.Trim() 14 | 15 | # Try to parse the date 16 | Try { 17 | [datetime]::ParseExact($InputString, "yyyy-MM-dd", $null) | Out-Null 18 | Return $true 19 | } 20 | Catch { 21 | Return $false 22 | } 23 | } 24 | 25 | Function Find-TrueOrFalse { 26 | Param ( 27 | [object]$Value 28 | ) 29 | # Return true if the value is either $true or $false 30 | Return $Value -eq $true -or $Value -eq $false 31 | } 32 | } 33 | 34 | If ($PSVersionTable.PSVersion.Major -le 6) { 35 | Describe "PS - Get-LatestOSBuild" { 36 | Context "Win 10 (1507)" { 37 | It "Results" { 38 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1507 -latestreleases 1000 39 | Start-Sleep -Seconds 0 40 | $Results.Build.Count | Should -BeGreaterThan 0 41 | $Results.Version | Should -Contain 'Version 1507 (RTM) (OS build 10240)' 42 | $Results.Build | Should -Match '^10240\.' 43 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 44 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 45 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 46 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 47 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 48 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 49 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 50 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 51 | } 52 | } 53 | Context "Win 10 (1511)" { 54 | It "Results" { 55 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1511 -latestreleases 1000 56 | Start-Sleep -Seconds 0 57 | $Results.Build.Count | Should -BeGreaterThan 0 58 | $Results.Version | Should -Contain 'Version 1511 (OS build 10586)' 59 | $Results.Build | Should -Match '^10586\.' 60 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 61 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 62 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 63 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 64 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 65 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 66 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 67 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 68 | } 69 | } 70 | Context "Win 10 / Server 2016 (1607)" { 71 | It "Results" { 72 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1607 -latestreleases 1000 73 | Start-Sleep -Seconds 0 74 | $Results.Build.Count | Should -BeGreaterThan 0 75 | $Results.Version | Should -Contain 'Version 1607 (OS build 14393)' 76 | $Results.Build | Should -Match '^14393\.' 77 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 78 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 79 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 80 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 81 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 82 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 83 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 84 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 85 | } 86 | } 87 | Context "Win 10 (1703)" { 88 | It "Results" { 89 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1703 -latestreleases 1000 90 | Start-Sleep -Seconds 0 91 | $Results.Build.Count | Should -BeGreaterThan 0 92 | $Results.Version | Should -Contain 'Version 1703 (OS build 15063)' 93 | $Results.Build | Should -Match '^15063\.' 94 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 95 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 96 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 97 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 98 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 99 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 100 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 101 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 102 | } 103 | } 104 | Context "Win 10 (1709)" { 105 | It "Results" { 106 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1709 -latestreleases 1000 107 | Start-Sleep -Seconds 0 108 | $Results.Build.Count | Should -BeGreaterThan 0 109 | $Results.Version | Should -Contain 'Version 1709 (OS build 16299)' 110 | $Results.Build | Should -Match '^16299\.' 111 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 112 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 113 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 114 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 115 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 116 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 117 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 118 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 119 | } 120 | } 121 | Context "Win 10 (1803)" { 122 | It "Results" { 123 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1803 -latestreleases 1000 124 | Start-Sleep -Seconds 0 125 | $Results.Build.Count | Should -BeGreaterThan 0 126 | $Results.Version | Should -Contain 'Version 1803 (OS build 17134)' 127 | $Results.Build | Should -Match '^17134\.' 128 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 129 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 130 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 131 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 132 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 133 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 134 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 135 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 136 | } 137 | } 138 | Context "Win 10 / Server 2019 (1809)" { 139 | It "Results" { 140 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1809 -latestreleases 1000 141 | Start-Sleep -Seconds 0 142 | $Results.Build.Count | Should -BeGreaterThan 0 143 | $Results.Version | Should -Contain 'Version 1809 (OS build 17763)' 144 | $Results.Build | Should -Match '^17763\.' 145 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 146 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 147 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 148 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 149 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 150 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 151 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 152 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 153 | } 154 | } 155 | Context "Win 10 (1903)" { 156 | It "Results" { 157 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1903 -latestreleases 1000 158 | Start-Sleep -Seconds 0 159 | $Results.Build.Count | Should -BeGreaterThan 0 160 | $Results.Version | Should -Contain 'Version 1903 (OS build 18362)' 161 | $Results.Build | Should -Match '^18362\.' 162 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 163 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 164 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 165 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 166 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 167 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 168 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 169 | } 170 | } 171 | Context "Win 10 (1909)" { 172 | It "Results" { 173 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1909 -latestreleases 1000 174 | Start-Sleep -Seconds 0 175 | $Results.Build.Count | Should -BeGreaterThan 0 176 | $Results.Version | Should -Contain 'Version 1909 (OS build 18363)' 177 | $Results.Build | Should -Match '^18363\.' 178 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 179 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 180 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 181 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 182 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 183 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 184 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 185 | } 186 | } 187 | Context "Win 10 (2004)" { 188 | It "Results" { 189 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 2004 -latestreleases 1000 190 | Start-Sleep -Seconds 0 191 | $Results.Build.Count | Should -BeGreaterThan 0 192 | $Results.Version | Should -Contain 'Version 2004 (OS build 19041)' 193 | $Results.Build | Should -Match '^19041\.' 194 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 195 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 196 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 197 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 198 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 199 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 200 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 201 | } 202 | } 203 | Context "Win 10 (20H2)" { 204 | It "Results" { 205 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 20H2 -latestreleases 1000 206 | Start-Sleep -Seconds 0 207 | $Results.Build.Count | Should -BeGreaterThan 0 208 | $Results.Version | Should -Contain 'Version 20H2 (OS build 19042)' 209 | $Results.Build | Should -Match '^19042\.' 210 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 211 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 212 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 213 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 214 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 215 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 216 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 217 | } 218 | } 219 | Context "Win 10 (21H1)" { 220 | It "Results" { 221 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 21H1 -latestreleases 1000 222 | Start-Sleep -Seconds 0 223 | $Results.Build.Count | Should -BeGreaterThan 0 224 | $Results.Version | Should -Contain 'Version 21H1 (OS build 19043)' 225 | $Results.Build | Should -Match '^19043\.' 226 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 227 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 228 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 229 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 230 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 231 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 232 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 233 | } 234 | } 235 | Context "Win 10 (21H2)" { 236 | It "Results" { 237 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 21H2 -latestreleases 1000 238 | Start-Sleep -Seconds 0 239 | $Results.Build.Count | Should -BeGreaterThan 0 240 | $Results.Version | Should -Contain 'Version 21H2 (OS build 19044)' 241 | $Results.Build | Should -Match '^19044\.' 242 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 243 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 244 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 245 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 246 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 247 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 248 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 249 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 250 | } 251 | } 252 | Context "Win 10 (22H2)" { 253 | It "Results" { 254 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -latestreleases 1000 255 | Start-Sleep -Seconds 0 256 | $Results.Build.Count | Should -BeGreaterThan 0 257 | $Results.Version | Should -Contain 'Version 22H2 (OS build 19045)' 258 | $Results.Build | Should -Match '^19045\.' 259 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 260 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 261 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 262 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 263 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 264 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 265 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 266 | } 267 | } 268 | Context "Win 11 (21H2)" { 269 | It "Results" { 270 | $Results = Get-LatestOSBuild -OSName Win11 -OSVersion 21H2 -latestreleases 1000 271 | Start-Sleep -Seconds 0 272 | $Results.Build.Count | Should -BeGreaterThan 0 273 | $Results.Version | Should -Contain 'Version 21H2 (OS build 22000)' 274 | $Results.Build | Should -Match '^22000\.' 275 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 276 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 277 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 278 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 279 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 280 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 281 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 282 | } 283 | } 284 | Context "Win 11 (22H2)" { 285 | It "Results" { 286 | $Results = Get-LatestOSBuild -OSName Win11 -OSVersion 22H2 -latestreleases 1000 287 | Start-Sleep -Seconds 0 288 | $Results.Build.Count | Should -BeGreaterThan 0 289 | $Results.Version | Should -Contain 'Version 22H2 (OS build 22621)' 290 | $Results.Build | Should -Match '^22621\.' 291 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 292 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 293 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 294 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 295 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 296 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 297 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 298 | } 299 | } 300 | Context "Win 11 (23H2)" { 301 | It "Results" { 302 | $Results = Get-LatestOSBuild -OSName Win11 -OSVersion 23H2 -latestreleases 1000 303 | Start-Sleep -Seconds 0 304 | $Results.Build.Count | Should -BeGreaterThan 0 305 | $Results.Version | Should -Contain 'Version 23H2 (OS build 22631)' 306 | $Results.Build | Should -Match '^22631\.' 307 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 308 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 309 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 310 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 311 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 312 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 313 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 314 | } 315 | } 316 | Context "Win 11 (24H2)" { 317 | It "Results" { 318 | $Results = Get-LatestOSBuild -OSName Win11 -OSVersion 24H2 -latestreleases 1000 319 | Start-Sleep -Seconds 0 320 | $Results.Build.Count | Should -BeGreaterThan 0 321 | $Results.Version | Should -Contain 'Version 24H2 (OS build 26100)' 322 | $Results.Build | Should -Match '^26100\.' 323 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 324 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 325 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 326 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 327 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 328 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 329 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 330 | } 331 | } 332 | Context "Windows 11 Hotpatch (24H2)" { 333 | It "Results" { 334 | $Results = Get-LatestOSBuild -OSName Win11Hotpatch -OSVersion 24H2 -latestreleases 1000 335 | Start-Sleep -Seconds 0 336 | $Results.Build.Count | Should -BeGreaterThan 0 337 | $Results.Version | Should -Contain 'Version 24H2 (OS build 26100)' 338 | $Results.Build | Should -Match '^26100\.' 339 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 340 | $Results.Hotpatch | Should -Not -BeNullOrEmpty 341 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 342 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 343 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 344 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 345 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 346 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 347 | } 348 | } 349 | Context "Server 2022 (21H2)" { 350 | It "Results" { 351 | $Results = Get-LatestOSBuild -OSName Server2022 -OSVersion 21H2 -latestreleases 1000 352 | Start-Sleep -Seconds 0 353 | $Results.Build.Count | Should -BeGreaterThan 0 354 | $Results.Version | Should -Contain 'Version 21H2 (OS build 20348)' 355 | $Results.Build | Should -Match '^20348\.' 356 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 357 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 358 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 359 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 360 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 361 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 362 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 363 | } 364 | } 365 | Context "Server 2022 Hotpatch (21H2)" { 366 | It "Results" { 367 | $Results = Get-LatestOSBuild -OSName Server2022Hotpatch -OSVersion 21H2 -latestreleases 1000 368 | Start-Sleep -Seconds 0 369 | $Results.Build.Count | Should -BeGreaterThan 0 370 | $Results.Version | Should -Contain 'Version 21H2 (OS build 20348)' 371 | $Results.Build | Should -Match '^20348\.' 372 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 373 | $Results.Hotpatch | Should -Not -BeNullOrEmpty 374 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 375 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 376 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 377 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 378 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 379 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 380 | } 381 | } 382 | Context "Server 2025 (24H2)" { 383 | It "Results" { 384 | $Results = Get-LatestOSBuild -OSName Server2025 -OSVersion 24H2 -latestreleases 1000 385 | Start-Sleep -Seconds 0 386 | $Results.Build.Count | Should -BeGreaterThan 0 387 | $Results.Version | Should -Contain 'Version 24H2 (OS build 26100)' 388 | $Results.Build | Should -Match '^26100\.' 389 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 390 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 391 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 392 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 393 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 394 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 395 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 396 | } 397 | } 398 | Context "Server SAC (1709)" { 399 | It "Results" { 400 | $Results = Get-LatestOSBuild -OSName ServerSAC -OSVersion 1709 -latestreleases 1000 401 | Start-Sleep -Seconds 0 402 | $Results.Build.Count | Should -BeGreaterThan 0 403 | $Results.Version | Should -Contain 'Version 1709 (OS build 16299)' 404 | $Results.Build | Should -Match '^16299\.' 405 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 406 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 407 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 408 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 409 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 410 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 411 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 412 | } 413 | } 414 | } 415 | Describe "PS - Get-CurrentOSBuild" { 416 | Context "Build only" { 417 | It "Results" { 418 | $Results = Get-CurrentOSBuild 419 | Start-Sleep -Seconds 0 420 | $Results.Count | Should -Be 1 421 | } 422 | } 423 | Context "Detailed" { 424 | It "Results" { 425 | $Results = Get-CurrentOSBuild -Detailed 426 | Start-Sleep -Seconds 0 427 | $Results.Build.Count | Should -Be 1 428 | $Results.Version | Should -Not -BeNullOrEmpty 429 | $Results.Build | Should -Not -BeNullOrEmpty 430 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 431 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 432 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 433 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 434 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 435 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 436 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 437 | } 438 | } 439 | Describe "Code Signing Certificate Test - WindowsOSBuild.psm1" { 440 | Context "File Signature Check" { 441 | It "Results" { 442 | $signature = Get-AuthenticodeSignature -FilePath "$((Split-Path -Path $PSScriptRoot -Parent).TrimEnd('\'))\WindowsOSBuild.psm1" 443 | $signature | Should -Not -BeNullOrEmpty 444 | $signature.SignatureType| Should -Be "Authenticode" 445 | $signature.Status | Should -Be "Valid" 446 | } 447 | } 448 | } 449 | Describe "Code Signing Certificate Test - WindowsOSBuild.psd1" { 450 | Context "File Signature Check" { 451 | It "Results" { 452 | $signature = Get-AuthenticodeSignature -FilePath "$((Split-Path -Path $PSScriptRoot -Parent).TrimEnd('\'))\WindowsOSBuild.psd1" 453 | $signature | Should -Not -BeNullOrEmpty 454 | $signature.SignatureType| Should -Be "Authenticode" 455 | $signature.Status | Should -Be "Valid" 456 | } 457 | } 458 | } 459 | Describe "Code Signing Certificate Test - Get-CurrentOSBuild.ps1" { 460 | Context "File Signature Check" { 461 | It "Results" { 462 | $signature = Get-AuthenticodeSignature -FilePath "$((Split-Path -Path $PSScriptRoot -Parent).TrimEnd('\'))\Public\Get-CurrentOSBuild.ps1" 463 | $signature | Should -Not -BeNullOrEmpty 464 | $signature.SignatureType| Should -Be "Authenticode" 465 | $signature.Status | Should -Be "Valid" 466 | } 467 | } 468 | } 469 | Describe "Code Signing Certificate Test - Get-LatestOSBuild.ps1" { 470 | Context "File Signature Check" { 471 | It "Results" { 472 | $signature = Get-AuthenticodeSignature -FilePath "$((Split-Path -Path $PSScriptRoot -Parent).TrimEnd('\'))\Public\Get-LatestOSBuild.ps1" 473 | $signature | Should -Not -BeNullOrEmpty 474 | $signature.SignatureType| Should -Be "Authenticode" 475 | $signature.Status | Should -Be "Valid" 476 | } 477 | } 478 | } 479 | Describe "Code Signing Certificate Test - Import-HtmlAgilityPack.ps1" { 480 | Context "File Signature Check" { 481 | It "Results" { 482 | $signature = Get-AuthenticodeSignature -FilePath "$((Split-Path -Path $PSScriptRoot -Parent).TrimEnd('\'))\Private\Import-HtmlAgilityPack.ps1" 483 | $signature | Should -Not -BeNullOrEmpty 484 | $signature.SignatureType| Should -Be "Authenticode" 485 | $signature.Status | Should -Be "Valid" 486 | } 487 | } 488 | } 489 | Describe "Code Signing Certificate Test - WindowOSBuild.Tests.ps1" { 490 | Context "File Signature Check" { 491 | It "Results" { 492 | $signature = Get-AuthenticodeSignature -FilePath "$((Split-Path -Path $PSScriptRoot -Parent).TrimEnd('\'))\CI\WindowOSBuild.Tests.ps1" 493 | $signature | Should -Not -BeNullOrEmpty 494 | $signature.SignatureType| Should -Be "Authenticode" 495 | $signature.Status | Should -Be "Valid" 496 | } 497 | } 498 | } 499 | } 500 | } 501 | Else { 502 | Describe "PWSH - Get-LatestOSBuild" { 503 | Describe "PS - Get-LatestOSBuild" { 504 | Context "Win 10 (1507)" { 505 | It "Results" { 506 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1507 -latestreleases 1000 507 | Start-Sleep -Seconds 0 508 | $Results.Build.Count | Should -BeGreaterThan 0 509 | $Results.Version | Should -Contain 'Version 1507 (RTM) (OS build 10240)' 510 | $Results.Build | Should -Match '^10240\.' 511 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 512 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 513 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 514 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 515 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 516 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 517 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 518 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 519 | } 520 | } 521 | Context "Win 10 (1511)" { 522 | It "Results" { 523 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1511 -latestreleases 1000 524 | Start-Sleep -Seconds 0 525 | $Results.Build.Count | Should -BeGreaterThan 0 526 | $Results.Version | Should -Contain 'Version 1511 (OS build 10586)' 527 | $Results.Build | Should -Match '^10586\.' 528 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 529 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 530 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 531 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 532 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 533 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 534 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 535 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 536 | } 537 | } 538 | Context "Win 10 / Server 2016 (1607)" { 539 | It "Results" { 540 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1607 -latestreleases 1000 541 | Start-Sleep -Seconds 0 542 | $Results.Build.Count | Should -BeGreaterThan 0 543 | $Results.Version | Should -Contain 'Version 1607 (OS build 14393)' 544 | $Results.Build | Should -Match '^14393\.' 545 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 546 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 547 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 548 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 549 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 550 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 551 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 552 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 553 | } 554 | } 555 | Context "Win 10 (1703)" { 556 | It "Results" { 557 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1703 -latestreleases 1000 558 | Start-Sleep -Seconds 0 559 | $Results.Build.Count | Should -BeGreaterThan 0 560 | $Results.Version | Should -Contain 'Version 1703 (OS build 15063)' 561 | $Results.Build | Should -Match '^15063\.' 562 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 563 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 564 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 565 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 566 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 567 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 568 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 569 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 570 | } 571 | } 572 | Context "Win 10 (1709)" { 573 | It "Results" { 574 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1709 -latestreleases 1000 575 | Start-Sleep -Seconds 0 576 | $Results.Build.Count | Should -BeGreaterThan 0 577 | $Results.Version | Should -Contain 'Version 1709 (OS build 16299)' 578 | $Results.Build | Should -Match '^16299\.' 579 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 580 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 581 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 582 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 583 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 584 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 585 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 586 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 587 | } 588 | } 589 | Context "Win 10 (1803)" { 590 | It "Results" { 591 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1803 -latestreleases 1000 592 | Start-Sleep -Seconds 0 593 | $Results.Build.Count | Should -BeGreaterThan 0 594 | $Results.Version | Should -Contain 'Version 1803 (OS build 17134)' 595 | $Results.Build | Should -Match '^17134\.' 596 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 597 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 598 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 599 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 600 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 601 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 602 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 603 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 604 | } 605 | } 606 | Context "Win 10 / Server 2019 (1809)" { 607 | It "Results" { 608 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1809 -latestreleases 1000 609 | Start-Sleep -Seconds 0 610 | $Results.Build.Count | Should -BeGreaterThan 0 611 | $Results.Version | Should -Contain 'Version 1809 (OS build 17763)' 612 | $Results.Build | Should -Match '^17763\.' 613 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 614 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 615 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 616 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 617 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 618 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 619 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 620 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 621 | } 622 | } 623 | Context "Win 10 (1903)" { 624 | It "Results" { 625 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1903 -latestreleases 1000 626 | Start-Sleep -Seconds 0 627 | $Results.Build.Count | Should -BeGreaterThan 0 628 | $Results.Version | Should -Contain 'Version 1903 (OS build 18362)' 629 | $Results.Build | Should -Match '^18362\.' 630 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 631 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 632 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 633 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 634 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 635 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 636 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 637 | } 638 | } 639 | Context "Win 10 (1909)" { 640 | It "Results" { 641 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 1909 -latestreleases 1000 642 | Start-Sleep -Seconds 0 643 | $Results.Build.Count | Should -BeGreaterThan 0 644 | $Results.Version | Should -Contain 'Version 1909 (OS build 18363)' 645 | $Results.Build | Should -Match '^18363\.' 646 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 647 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 648 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 649 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 650 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 651 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 652 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 653 | } 654 | } 655 | Context "Win 10 (2004)" { 656 | It "Results" { 657 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 2004 -latestreleases 1000 658 | Start-Sleep -Seconds 0 659 | $Results.Build.Count | Should -BeGreaterThan 0 660 | $Results.Version | Should -Contain 'Version 2004 (OS build 19041)' 661 | $Results.Build | Should -Match '^19041\.' 662 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 663 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 664 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 665 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 666 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 667 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 668 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 669 | } 670 | } 671 | Context "Win 10 (20H2)" { 672 | It "Results" { 673 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 20H2 -latestreleases 1000 674 | Start-Sleep -Seconds 0 675 | $Results.Build.Count | Should -BeGreaterThan 0 676 | $Results.Version | Should -Contain 'Version 20H2 (OS build 19042)' 677 | $Results.Build | Should -Match '^19042\.' 678 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 679 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 680 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 681 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 682 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 683 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 684 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 685 | } 686 | } 687 | Context "Win 10 (21H1)" { 688 | It "Results" { 689 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 21H1 -latestreleases 1000 690 | Start-Sleep -Seconds 0 691 | $Results.Build.Count | Should -BeGreaterThan 0 692 | $Results.Version | Should -Contain 'Version 21H1 (OS build 19043)' 693 | $Results.Build | Should -Match '^19043\.' 694 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 695 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 696 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 697 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 698 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 699 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 700 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 701 | } 702 | } 703 | Context "Win 10 (21H2)" { 704 | It "Results" { 705 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 21H2 -latestreleases 1000 706 | Start-Sleep -Seconds 0 707 | $Results.Build.Count | Should -BeGreaterThan 0 708 | $Results.Version | Should -Contain 'Version 21H2 (OS build 19044)' 709 | $Results.Build | Should -Match '^19044\.' 710 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 711 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 712 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 713 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 714 | $Results.'Servicing option' | ForEach-Object { $_ -match "•|\u2022" } | Where-Object { $_ -eq $true } 715 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 716 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 717 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 718 | } 719 | } 720 | Context "Win 10 (22H2)" { 721 | It "Results" { 722 | $Results = Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -latestreleases 1000 723 | Start-Sleep -Seconds 0 724 | $Results.Build.Count | Should -BeGreaterThan 0 725 | $Results.Version | Should -Contain 'Version 22H2 (OS build 19045)' 726 | $Results.Build | Should -Match '^19045\.' 727 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 728 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 729 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 730 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 731 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 732 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 733 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 734 | } 735 | } 736 | Context "Win 11 (21H2)" { 737 | It "Results" { 738 | $Results = Get-LatestOSBuild -OSName Win11 -OSVersion 21H2 -latestreleases 1000 739 | Start-Sleep -Seconds 0 740 | $Results.Build.Count | Should -BeGreaterThan 0 741 | $Results.Version | Should -Contain 'Version 21H2 (OS build 22000)' 742 | $Results.Build | Should -Match '^22000\.' 743 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 744 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 745 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 746 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 747 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 748 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 749 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 750 | } 751 | } 752 | Context "Win 11 (22H2)" { 753 | It "Results" { 754 | $Results = Get-LatestOSBuild -OSName Win11 -OSVersion 22H2 -latestreleases 1000 755 | Start-Sleep -Seconds 0 756 | $Results.Build.Count | Should -BeGreaterThan 0 757 | $Results.Version | Should -Contain 'Version 22H2 (OS build 22621)' 758 | $Results.Build | Should -Match '^22621\.' 759 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 760 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 761 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 762 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 763 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 764 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 765 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 766 | } 767 | } 768 | Context "Win 11 (23H2)" { 769 | It "Results" { 770 | $Results = Get-LatestOSBuild -OSName Win11 -OSVersion 23H2 -latestreleases 1000 771 | Start-Sleep -Seconds 0 772 | $Results.Build.Count | Should -BeGreaterThan 0 773 | $Results.Version | Should -Contain 'Version 23H2 (OS build 22631)' 774 | $Results.Build | Should -Match '^22631\.' 775 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 776 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 777 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 778 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 779 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 780 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 781 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 782 | } 783 | } 784 | Context "Win 11 (24H2)" { 785 | It "Results" { 786 | $Results = Get-LatestOSBuild -OSName Win11 -OSVersion 24H2 -latestreleases 1000 787 | Start-Sleep -Seconds 0 788 | $Results.Build.Count | Should -BeGreaterThan 0 789 | $Results.Version | Should -Contain 'Version 24H2 (OS build 26100)' 790 | $Results.Build | Should -Match '^26100\.' 791 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 792 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 793 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 794 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 795 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 796 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 797 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 798 | } 799 | } 800 | Context "Windows 11 Hotpatch (24H2)" { 801 | It "Results" { 802 | $Results = Get-LatestOSBuild -OSName Win11Hotpatch -OSVersion 24H2 -latestreleases 1000 803 | Start-Sleep -Seconds 0 804 | $Results.Build.Count | Should -BeGreaterThan 0 805 | $Results.Version | Should -Contain 'Version 24H2 (OS build 26100)' 806 | $Results.Build | Should -Match '^26100\.' 807 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 808 | $Results.Hotpatch | Should -Not -BeNullOrEmpty 809 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 810 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 811 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 812 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 813 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 814 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 815 | } 816 | } 817 | Context "Server 2022 (21H2)" { 818 | It "Results" { 819 | $Results = Get-LatestOSBuild -OSName Server2022 -OSVersion 21H2 -latestreleases 1000 820 | Start-Sleep -Seconds 0 821 | $Results.Build.Count | Should -BeGreaterThan 0 822 | $Results.Version | Should -Contain 'Version 21H2 (OS build 20348)' 823 | $Results.Build | Should -Match '^20348\.' 824 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 825 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 826 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 827 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 828 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 829 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 830 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 831 | } 832 | } 833 | Context "Server 2022 Hotpatch (21H2)" { 834 | It "Results" { 835 | $Results = Get-LatestOSBuild -OSName Server2022Hotpatch -OSVersion 21H2 -latestreleases 1000 836 | Start-Sleep -Seconds 0 837 | $Results.Build.Count | Should -BeGreaterThan 0 838 | $Results.Version | Should -Contain 'Version 21H2 (OS build 20348)' 839 | $Results.Build | Should -Match '^20348\.' 840 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 841 | $Results.Hotpatch | Should -Not -BeNullOrEmpty 842 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 843 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 844 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 845 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 846 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 847 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 848 | } 849 | } 850 | Context "Server 2025 (24H2)" { 851 | It "Results" { 852 | $Results = Get-LatestOSBuild -OSName Server2025 -OSVersion 24H2 -latestreleases 1000 853 | Start-Sleep -Seconds 0 854 | $Results.Build.Count | Should -BeGreaterThan 0 855 | $Results.Version | Should -Contain 'Version 24H2 (OS build 26100)' 856 | $Results.Build | Should -Match '^26100\.' 857 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 858 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 859 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 860 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 861 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 862 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 863 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 864 | } 865 | } 866 | Context "Server SAC (1709)" { 867 | It "Results" { 868 | $Results = Get-LatestOSBuild -OSName ServerSAC -OSVersion 1709 -latestreleases 1000 869 | Start-Sleep -Seconds 0 870 | $Results.Build.Count | Should -BeGreaterThan 0 871 | $Results.Version | Should -Contain 'Version 1709 (OS build 16299)' 872 | $Results.Build | Should -Match '^16299\.' 873 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 874 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 875 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 876 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 877 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 878 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 879 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 880 | } 881 | } 882 | } 883 | } 884 | 885 | Describe "PWSH - Get-CurrentOSBuild" { 886 | Context "Build only" { 887 | It "Results" { 888 | $Results = Get-CurrentOSBuild 889 | Start-Sleep -Seconds 0 890 | $Results.Count | Should -Be 1 891 | } 892 | } 893 | Context "Detailed" { 894 | It "Results" { 895 | $Results = Get-CurrentOSBuild -Detailed 896 | Start-Sleep -Seconds 0 897 | $Results.Build.Count | Should -Be 1 898 | $Results.Version | Should -Not -BeNullOrEmpty 899 | $Results.Build | Should -Not -BeNullOrEmpty 900 | $Results.'Availability date' | ForEach-Object { Find-ValidDate $_ } | Where-Object { $_ -eq $true } 901 | $Results.Preview | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 902 | $Results.'Out-of-band' | ForEach-Object { Find-TrueOrFalse $_ } | Where-Object { $_ -eq $true } 903 | $Results.'Servicing option' | Should -Not -BeNullOrEmpty 904 | $Results.'KB article' | Should -Match "^KB\d+( / KB\d+)*$|^N/A$" 905 | $Results.'KB URL' | Should -Match "^\s*(https://support.microsoft.com/([a-z]{2}-[a-z]{2})?/help/\d+)\s*$|^\s*N/A\s*$" 906 | $Results.'Catalog URL' | Should -Match "https://www.catalog.update.microsoft.com/Search.aspx\?q=KB\d+|^N/A$" 907 | } 908 | } 909 | Describe "Code Signing Certificate Test - WindowsOSBuild.psm1" { 910 | Context "File Signature Check" { 911 | It "Results" { 912 | $signature = Get-AuthenticodeSignature -FilePath "$((Split-Path -Path $PSScriptRoot -Parent).TrimEnd('\'))\WindowsOSBuild.psm1" 913 | $signature | Should -Not -BeNullOrEmpty 914 | $signature.SignatureType| Should -Be "Authenticode" 915 | $signature.Status | Should -Be "Valid" 916 | } 917 | } 918 | } 919 | Describe "Code Signing Certificate Test - WindowsOSBuild.psd1" { 920 | Context "File Signature Check" { 921 | It "Results" { 922 | $signature = Get-AuthenticodeSignature -FilePath "$((Split-Path -Path $PSScriptRoot -Parent).TrimEnd('\'))\WindowsOSBuild.psd1" 923 | $signature | Should -Not -BeNullOrEmpty 924 | $signature.SignatureType| Should -Be "Authenticode" 925 | $signature.Status | Should -Be "Valid" 926 | } 927 | } 928 | } 929 | Describe "Code Signing Certificate Test - Get-CurrentOSBuild.ps1" { 930 | Context "File Signature Check" { 931 | It "Results" { 932 | $signature = Get-AuthenticodeSignature -FilePath "$((Split-Path -Path $PSScriptRoot -Parent).TrimEnd('\'))\Public\Get-CurrentOSBuild.ps1" 933 | $signature | Should -Not -BeNullOrEmpty 934 | $signature.SignatureType| Should -Be "Authenticode" 935 | $signature.Status | Should -Be "Valid" 936 | } 937 | } 938 | } 939 | Describe "Code Signing Certificate Test - Get-LatestOSBuild.ps1" { 940 | Context "File Signature Check" { 941 | It "Results" { 942 | $signature = Get-AuthenticodeSignature -FilePath "$((Split-Path -Path $PSScriptRoot -Parent).TrimEnd('\'))\Public\Get-LatestOSBuild.ps1" 943 | $signature | Should -Not -BeNullOrEmpty 944 | $signature.SignatureType| Should -Be "Authenticode" 945 | $signature.Status | Should -Be "Valid" 946 | } 947 | } 948 | } 949 | Describe "Code Signing Certificate Test - Import-HtmlAgilityPack.ps1" { 950 | Context "File Signature Check" { 951 | It "Results" { 952 | $signature = Get-AuthenticodeSignature -FilePath "$((Split-Path -Path $PSScriptRoot -Parent).TrimEnd('\'))\Private\Import-HtmlAgilityPack.ps1" 953 | $signature | Should -Not -BeNullOrEmpty 954 | $signature.SignatureType| Should -Be "Authenticode" 955 | $signature.Status | Should -Be "Valid" 956 | } 957 | } 958 | } 959 | Describe "Code Signing Certificate Test - WindowOSBuild.Tests.ps1" { 960 | Context "File Signature Check" { 961 | It "Results" { 962 | $signature = Get-AuthenticodeSignature -FilePath "$((Split-Path -Path $PSScriptRoot -Parent).TrimEnd('\'))\CI\WindowOSBuild.Tests.ps1" 963 | $signature | Should -Not -BeNullOrEmpty 964 | $signature.SignatureType| Should -Be "Authenticode" 965 | $signature.Status | Should -Be "Valid" 966 | } 967 | } 968 | } 969 | } 970 | } 971 | # SIG # Begin signature block 972 | # MIImbAYJKoZIhvcNAQcCoIImXTCCJlkCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB 973 | # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR 974 | # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUG8VWzO9rPKpJYuTBthJqqrew 975 | # WOiggiAnMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B 976 | # AQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD 977 | # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk 978 | # IElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQsw 979 | # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu 980 | # ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw 981 | # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz 982 | # 7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS 983 | # 5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7 984 | # bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfI 985 | # SKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jH 986 | # trHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14 987 | # Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2 988 | # h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt 989 | # 6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPR 990 | # iQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ER 991 | # ElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4K 992 | # Jpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAd 993 | # BgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SS 994 | # y4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAk 995 | # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAC 996 | # hjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS 997 | # b290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 998 | # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRV 999 | # HSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyh 1000 | # hyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO 1001 | # 0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo 1002 | # 8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++h 1003 | # UD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5x 1004 | # aiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMIIGYzCCBEug 1005 | # AwIBAgIQeAuTgzemd0ILREkKU+Yq2jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQG 1006 | # EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMSQwIgYDVQQD 1007 | # ExtDZXJ0dW0gQ29kZSBTaWduaW5nIDIwMjEgQ0EwHhcNMjQwNDExMDYwMzIxWhcN 1008 | # MjUwNDExMDYwMzIwWjCBiDELMAkGA1UEBhMCR0IxDzANBgNVBAgMBkRvcnNldDEU 1009 | # MBIGA1UEBwwLQk9VUk5FTU9VVEgxHjAcBgNVBAoMFU9wZW4gU291cmNlIERldmVs 1010 | # b3BlcjEyMDAGA1UEAwwpT3BlbiBTb3VyY2UgRGV2ZWxvcGVyLCBBU0hMRVkgTUlD 1011 | # SEFFTCBIT1cwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDpmsgFPzl4 1012 | # 7W61kLLEp5ljxHC0ZZDti0+DL2JSAac1+bQW24vSjg4ABHhRB5CDKBuwVe2h0l+G 1013 | # mEZHhKc9cz/RB+hUIJycd5Qx6VzsI1KJ0heEECm+oo3rywyqrd9RovkhkU2X29cR 1014 | # UAa9SWZJJ2+/ImyzfyxzR+u0DD17BucHXWylQB2HGFCcX3kYUmgyZ/ANrgTvetW+ 1015 | # n91OLxquC5+Nslh4MhbQAnItX79qrFLODd05S3SpQvdti16WGcRwXka4t5zdAMf6 1016 | # v3c8ThHKPm/1TsyWsYAUMYJ9C0sNt+QYKNYHRX7DuA1OJBngAyGggtaXmqEpPBX2 1017 | # SkDJ0uOeVDoJEOsxNydGZYPgvkIzsyF8YmEzkPK5x5elglYI0wfGwaMKshVbszj5 1018 | # KXIPogeF/0vrEi8iIEd+Ro3ZY8ul+TliYf6P55tl3VCuKHDbzcYCtOXURmAPGwxC 1019 | # 9wVvTr946eJr+emejOxg4/BZw5Q5GD6Qr8wwyodqholbzp8bfjTFmC8CAwEAAaOC 1020 | # AXgwggF0MAwGA1UdEwEB/wQCMAAwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2Nj 1021 | # c2NhMjAyMS5jcmwuY2VydHVtLnBsL2Njc2NhMjAyMS5jcmwwcwYIKwYBBQUHAQEE 1022 | # ZzBlMCwGCCsGAQUFBzABhiBodHRwOi8vY2NzY2EyMDIxLm9jc3AtY2VydHVtLmNv 1023 | # bTA1BggrBgEFBQcwAoYpaHR0cDovL3JlcG9zaXRvcnkuY2VydHVtLnBsL2Njc2Nh 1024 | # MjAyMS5jZXIwHwYDVR0jBBgwFoAU3XRdTADbe5+gdMqxbvc8wDLAcM0wHQYDVR0O 1025 | # BBYEFB7BnDzi+HIrft6IpueXUsx5LcgwMEsGA1UdIAREMEIwCAYGZ4EMAQQBMDYG 1026 | # CyqEaAGG9ncCBQEEMCcwJQYIKwYBBQUHAgEWGWh0dHBzOi8vd3d3LmNlcnR1bS5w 1027 | # bC9DUFMwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDgYDVR0PAQH/BAQDAgeAMA0GCSqG 1028 | # SIb3DQEBCwUAA4ICAQBO5qPmZq+cztnjKtz9DyVBkZGaHj/TmfIZHrYfeQ0zdEVL 1029 | # EszgokLuqNDdk0odEUHiockPB2dQn60oE3rNs+Wb1ZLLT18VoQTV0saMD3GiNzil 1030 | # ejD4nIrhQ+vt0auxCvzBS8cQd24ePmjTqcIkL/u07xGhtT3LpUHUuHknUcEFjgs0 1031 | # bUpGR5bofW8B9ZSC31g2i5PKZH8PUgOrTvg8oaMQYWyduKFnW8JRRGqypjUIFDE0 1032 | # N224ox/U6GqqIl2cuC87H7WrHPEO6VjqSOx0PgybhSggGDKRNk9UQN1R45K/NCcw 1033 | # 5+sIA1pjTZHnMhIJdxamhXiNq2S0U3LRVLSs1/BuXGENFWUraE4c51kDCiBPpGus 1034 | # olI7/LLF3PIyYopyAWOGw0R7snlT+HJbfI7P6ObfYzzmIMdrKSaBkNtautcRYcIT 1035 | # HAmbUAVplnpexQXXapSqxUfrPXWZk7xRLSXXqn915NbAoofVrTuLNXbv437KmoaN 1036 | # p2J23oE7KzqdkoZ9SO4+8K+XKoEqBrPyxNB/i5UIId1Rsu5GE453usJf7zgsz4Ib 1037 | # T8MQXjPq0WageEH3cL3qoPGBVbD++hLCJhqHPFJfM3zqxz4xZIRm7dY7GmcVc3Qq 1038 | # H0biPnYkTfe8fwrT/IpEmVPdDnUSM92MhV25HV4CYU5LAISU1B070DMFAGc1uTCC 1039 | # Bq4wggSWoAMCAQICEAc2N7ckVHzYR6z9KGYqXlswDQYJKoZIhvcNAQELBQAwYjEL 1040 | # MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 1041 | # LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0 1042 | # MB4XDTIyMDMyMzAwMDAwMFoXDTM3MDMyMjIzNTk1OVowYzELMAkGA1UEBhMCVVMx 1043 | # FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVz 1044 | # dGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTCCAiIwDQYJKoZI 1045 | # hvcNAQEBBQADggIPADCCAgoCggIBAMaGNQZJs8E9cklRVcclA8TykTepl1Gh1tKD 1046 | # 0Z5Mom2gsMyD+Vr2EaFEFUJfpIjzaPp985yJC3+dH54PMx9QEwsmc5Zt+FeoAn39 1047 | # Q7SE2hHxc7Gz7iuAhIoiGN/r2j3EF3+rGSs+QtxnjupRPfDWVtTnKC3r07G1decf 1048 | # BmWNlCnT2exp39mQh0YAe9tEQYncfGpXevA3eZ9drMvohGS0UvJ2R/dhgxndX7RU 1049 | # CyFobjchu0CsX7LeSn3O9TkSZ+8OpWNs5KbFHc02DVzV5huowWR0QKfAcsW6Th+x 1050 | # tVhNef7Xj3OTrCw54qVI1vCwMROpVymWJy71h6aPTnYVVSZwmCZ/oBpHIEPjQ2OA 1051 | # e3VuJyWQmDo4EbP29p7mO1vsgd4iFNmCKseSv6De4z6ic/rnH1pslPJSlRErWHRA 1052 | # KKtzQ87fSqEcazjFKfPKqpZzQmiftkaznTqj1QPgv/CiPMpC3BhIfxQ0z9JMq++b 1053 | # Pf4OuGQq+nUoJEHtQr8FnGZJUlD0UfM2SU2LINIsVzV5K6jzRWC8I41Y99xh3pP+ 1054 | # OcD5sjClTNfpmEpYPtMDiP6zj9NeS3YSUZPJjAw7W4oiqMEmCPkUEBIDfV8ju2Tj 1055 | # Y+Cm4T72wnSyPx4JduyrXUZ14mCjWAkBKAAOhFTuzuldyF4wEr1GnrXTdrnSDmuZ 1056 | # DNIztM2xAgMBAAGjggFdMIIBWTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW 1057 | # BBS6FtltTYUvcyl2mi91jGogj57IbzAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/ 1058 | # 57qYrhwPTzAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwdwYI 1059 | # KwYBBQUHAQEEazBpMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j 1060 | # b20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdp 1061 | # Q2VydFRydXN0ZWRSb290RzQuY3J0MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9j 1062 | # cmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3JsMCAGA1Ud 1063 | # IAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEA 1064 | # fVmOwJO2b5ipRCIBfmbW2CFC4bAYLhBNE88wU86/GPvHUF3iSyn7cIoNqilp/GnB 1065 | # zx0H6T5gyNgL5Vxb122H+oQgJTQxZ822EpZvxFBMYh0MCIKoFr2pVs8Vc40BIiXO 1066 | # lWk/R3f7cnQU1/+rT4osequFzUNf7WC2qk+RZp4snuCKrOX9jLxkJodskr2dfNBw 1067 | # CnzvqLx1T7pa96kQsl3p/yhUifDVinF2ZdrM8HKjI/rAJ4JErpknG6skHibBt94q 1068 | # 6/aesXmZgaNWhqsKRcnfxI2g55j7+6adcq/Ex8HBanHZxhOACcS2n82HhyS7T6NJ 1069 | # uXdmkfFynOlLAlKnN36TU6w7HQhJD5TNOXrd/yVjmScsPT9rp/Fmw0HNT7ZAmyEh 1070 | # QNC3EyTN3B14OuSereU0cZLXJmvkOHOrpgFPvT87eK1MrfvElXvtCl8zOYdBeHo4 1071 | # 6Zzh3SP9HSjTx/no8Zhf+yvYfvJGnXUsHicsJttvFXseGYs2uJPU5vIXmVnKcPA3 1072 | # v5gA3yAWTyf7YGcWoWa63VXAOimGsJigK+2VQbc61RWYMbRiCQ8KvYHZE/6/pNHz 1073 | # V9m8BPqC3jLfBInwAM1dwvnQI38AC+R2AibZ8GV2QqYphwlHK+Z/GqSFD/yYlvZV 1074 | # VCsfgPrA8g4r5db7qS9EFUrnEw4d2zc4GqEr9u3WfPwwgga5MIIEoaADAgECAhEA 1075 | # maOACiZVO2Wr3G6EprPqOTANBgkqhkiG9w0BAQwFADCBgDELMAkGA1UEBhMCUEwx 1076 | # IjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNl 1077 | # cnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRy 1078 | # dXN0ZWQgTmV0d29yayBDQSAyMB4XDTIxMDUxOTA1MzIxOFoXDTM2MDUxODA1MzIx 1079 | # OFowVjELMAkGA1UEBhMCUEwxITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMg 1080 | # Uy5BLjEkMCIGA1UEAxMbQ2VydHVtIENvZGUgU2lnbmluZyAyMDIxIENBMIICIjAN 1081 | # BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnSPPBDAjO8FGLOczcz5jXXp1ur5c 1082 | # Tbq96y34vuTmflN4mSAfgLKTvggv24/rWiVGzGxT9YEASVMw1Aj8ewTS4IndU8s7 1083 | # VS5+djSoMcbvIKck6+hI1shsylP4JyLvmxwLHtSworV9wmjhNd627h27a8RdrT1P 1084 | # H9ud0IF+njvMk2xqbNTIPsnWtw3E7DmDoUmDQiYi/ucJ42fcHqBkbbxYDB7SYOou 1085 | # u9Tj1yHIohzuC8KNqfcYf7Z4/iZgkBJ+UFNDcc6zokZ2uJIxWgPWXMEmhu1gMXgv 1086 | # 8aGUsRdaCtVD2bSlbfsq7BiqljjaCun+RJgTgFRCtsuAEw0pG9+FA+yQN9n/kZtM 1087 | # LK+Wo837Q4QOZgYqVWQ4x6cM7/G0yswg1ElLlJj6NYKLw9EcBXE7TF3HybZtYvj9 1088 | # lDV2nT8mFSkcSkAExzd4prHwYjUXTeZIlVXqj+eaYqoMTpMrfh5MCAOIG5knN4Q/ 1089 | # JHuurfTI5XDYO962WZayx7ACFf5ydJpoEowSP07YaBiQ8nXpDkNrUA9g7qf/rCkK 1090 | # bWpQ5boufUnq1UiYPIAHlezf4muJqxqIns/kqld6JVX8cixbd6PzkDpwZo4SlADa 1091 | # Ci2JSplKShBSND36E/ENVv8urPS0yOnpG4tIoBGxVCARPCg1BnyMJ4rBJAcOSnAW 1092 | # d18Jx5n858JSqPECAwEAAaOCAVUwggFRMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O 1093 | # BBYEFN10XUwA23ufoHTKsW73PMAywHDNMB8GA1UdIwQYMBaAFLahVDkCw6A/joq8 1094 | # +tT4HKbROg79MA4GA1UdDwEB/wQEAwIBBjATBgNVHSUEDDAKBggrBgEFBQcDAzAw 1095 | # BgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vY3JsLmNlcnR1bS5wbC9jdG5jYTIuY3Js 1096 | # MGwGCCsGAQUFBwEBBGAwXjAoBggrBgEFBQcwAYYcaHR0cDovL3N1YmNhLm9jc3At 1097 | # Y2VydHVtLmNvbTAyBggrBgEFBQcwAoYmaHR0cDovL3JlcG9zaXRvcnkuY2VydHVt 1098 | # LnBsL2N0bmNhMi5jZXIwOQYDVR0gBDIwMDAuBgRVHSAAMCYwJAYIKwYBBQUHAgEW 1099 | # GGh0dHA6Ly93d3cuY2VydHVtLnBsL0NQUzANBgkqhkiG9w0BAQwFAAOCAgEAdYhY 1100 | # D+WPUCiaU58Q7EP89DttyZqGYn2XRDhJkL6P+/T0IPZyxfxiXumYlARMgwRzLRUS 1101 | # tJl490L94C9LGF3vjzzH8Jq3iR74BRlkO18J3zIdmCKQa5LyZ48IfICJTZVJeChD 1102 | # UyuQy6rGDxLUUAsO0eqeLNhLVsgw6/zOfImNlARKn1FP7o0fTbj8ipNGxHBIutiR 1103 | # sWrhWM2f8pXdd3x2mbJCKKtl2s42g9KUJHEIiLni9ByoqIUul4GblLQigO0ugh7b 1104 | # WRLDm0CdY9rNLqyA3ahe8WlxVWkxyrQLjH8ItI17RdySaYayX3PhRSC4Am1/7mAT 1105 | # wZWwSD+B7eMcZNhpn8zJ+6MTyE6YoEBSRVrs0zFFIHUR08Wk0ikSf+lIe5Iv6RY3 1106 | # /bFAEloMU+vUBfSouCReZwSLo8WdrDlPXtR0gicDnytO7eZ5827NS2x7gCBibESY 1107 | # kOh1/w1tVxTpV2Na3PR7nxYVlPu1JPoRZCbH86gc96UTvuWiOruWmyOEMLOGGniR 1108 | # +x+zPF/2DaGgK2W1eEJfo2qyrBNPvF7wuAyQfiFXLwvWHamoYtPZo0LHuH8X3n9C 1109 | # +xN4YaNjt2ywzOr+tKyEVAotnyU9vyEVOaIYMk3IeBrmFnn0gbKeTTyYeEEUz/Qw 1110 | # t4HOUBCrW602NCmvO1nm+/80nLy5r0AZvCQxaQ4wgga8MIIEpKADAgECAhALrma8 1111 | # Wrp/lYfG+ekE4zMEMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcwFQYD 1112 | # VQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBH 1113 | # NCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMjQwOTI2MDAwMDAw 1114 | # WhcNMzUxMTI1MjM1OTU5WjBCMQswCQYDVQQGEwJVUzERMA8GA1UEChMIRGlnaUNl 1115 | # cnQxIDAeBgNVBAMTF0RpZ2lDZXJ0IFRpbWVzdGFtcCAyMDI0MIICIjANBgkqhkiG 1116 | # 9w0BAQEFAAOCAg8AMIICCgKCAgEAvmpzn/aVIauWMLpbbeZZo7Xo/ZEfGMSIO2qZ 1117 | # 46XB/QowIEMSvgjEdEZ3v4vrrTHleW1JWGErrjOL0J4L0HqVR1czSzvUQ5xF7z4I 1118 | # Qmn7dHY7yijvoQ7ujm0u6yXF2v1CrzZopykD07/9fpAT4BxpT9vJoJqAsP8YuhRv 1119 | # flJ9YeHjes4fduksTHulntq9WelRWY++TFPxzZrbILRYynyEy7rS1lHQKFpXvo2G 1120 | # ePfsMRhNf1F41nyEg5h7iOXv+vjX0K8RhUisfqw3TTLHj1uhS66YX2LZPxS4oaf3 1121 | # 3rp9HlfqSBePejlYeEdU740GKQM7SaVSH3TbBL8R6HwX9QVpGnXPlKdE4fBIn5BB 1122 | # FnV+KwPxRNUNK6lYk2y1WSKour4hJN0SMkoaNV8hyyADiX1xuTxKaXN12HgR+8Wu 1123 | # lU2d6zhzXomJ2PleI9V2yfmfXSPGYanGgxzqI+ShoOGLomMd3mJt92nm7Mheng/T 1124 | # BeSA2z4I78JpwGpTRHiT7yHqBiV2ngUIyCtd0pZ8zg3S7bk4QC4RrcnKJ3FbjyPA 1125 | # GogmoiZ33c1HG93Vp6lJ415ERcC7bFQMRbxqrMVANiav1k425zYyFMyLNyE1QulQ 1126 | # SgDpW9rtvVcIH7WvG9sqYup9j8z9J1XqbBZPJ5XLln8mS8wWmdDLnBHXgYly/p1D 1127 | # hoQo5fkCAwEAAaOCAYswggGHMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAA 1128 | # MBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsG 1129 | # CWCGSAGG/WwHATAfBgNVHSMEGDAWgBS6FtltTYUvcyl2mi91jGogj57IbzAdBgNV 1130 | # HQ4EFgQUn1csA3cOKBWQZqVjXu5Pkh92oFswWgYDVR0fBFMwUTBPoE2gS4ZJaHR0 1131 | # cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5NlNI 1132 | # QTI1NlRpbWVTdGFtcGluZ0NBLmNybDCBkAYIKwYBBQUHAQEEgYMwgYAwJAYIKwYB 1133 | # BQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBYBggrBgEFBQcwAoZMaHR0 1134 | # cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5 1135 | # NlNIQTI1NlRpbWVTdGFtcGluZ0NBLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAPa0e 1136 | # H3aZW+M4hBJH2UOR9hHbm04IHdEoT8/T3HuBSyZeq3jSi5GXeWP7xCKhVireKCnC 1137 | # s+8GZl2uVYFvQe+pPTScVJeCZSsMo1JCoZN2mMew/L4tpqVNbSpWO9QGFwfMEy60 1138 | # HofN6V51sMLMXNTLfhVqs+e8haupWiArSozyAmGH/6oMQAh078qRh6wvJNU6gnh5 1139 | # OruCP1QUAvVSu4kqVOcJVozZR5RRb/zPd++PGE3qF1P3xWvYViUJLsxtvge/mzA7 1140 | # 5oBfFZSbdakHJe2BVDGIGVNVjOp8sNt70+kEoMF+T6tptMUNlehSR7vM+C13v9+9 1141 | # ZOUKzfRUAYSyyEmYtsnpltD/GWX8eM70ls1V6QG/ZOB6b6Yum1HvIiulqJ1Elesj 1142 | # 5TMHq8CWT/xrW7twipXTJ5/i5pkU5E16RSBAdOp12aw8IQhhA/vEbFkEiF2abhuF 1143 | # ixUDobZaA0VhqAsMHOmaT3XThZDNi5U2zHKhUs5uHHdG6BoQau75KiNbh0c+hatS 1144 | # F+02kULkftARjsyEpHKsF7u5zKRbt5oK5YGwFvgc4pEVUNytmB3BpIiowOIIuDgP 1145 | # 5M9WArHYSAR16gc0dP2XdkMEP5eBsX7bf/MGN4K3HP50v/01ZHo/Z5lGLvNwQ7XH 1146 | # Bx1yomzLP8lx4Q1zZKDyHcp4VQJLu2kWTsKsOqQxggWvMIIFqwIBATBqMFYxCzAJ 1147 | # BgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAi 1148 | # BgNVBAMTG0NlcnR1bSBDb2RlIFNpZ25pbmcgMjAyMSBDQQIQeAuTgzemd0ILREkK 1149 | # U+Yq2jAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkq 1150 | # hkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGC 1151 | # NwIBFTAjBgkqhkiG9w0BCQQxFgQUV6gX4Olbfp/axF6XpdHJWw6FrdwwDQYJKoZI 1152 | # hvcNAQEBBQAEggGAOMDgKtVpBZtiZOHK8lNiZNuFLLNPDhSUtclVltXYbPFCLtBg 1153 | # gajX47HejHPjSIZDqGBnNjaf1tCVqaO0rXOeayGQDP7wHse5rBKHqtw73EsEGlrC 1154 | # tbrDMIi61VlO9IWOVQqHvOnAxTouJ9sO1TLWTdvTVGG29xEiY5JxdwO4VHbDjQR5 1155 | # JcN6TggidhuPJfECwPApzrvA8CapnxlHAlSpSY94kd019YuvDCONDrFQIhJIMtDd 1156 | # 106aKTx+O3PW6HN1QqleExw5ZB/bQ3z7OEoCabE8o7jVAyEO51mxbhiFnl8TdkGl 1157 | # 4h4XQTaU24i2JvtdChJJwvlLN71kx/1D/5ZmAR2BSKeHIvTG/XdpHA5K87XaYjVB 1158 | # BVifWFc4lJ//JHm4gEjHvvnA2M8odlAywkUleO6V0tHkMqpbsZV4zB8+YWVxkJzB 1159 | # pW6Ap4iFASNgrAhCIo9Ip0BZI7OqFZu+C5Mfg7W6QVh0VkJoMLy2rzsjn11/gydr 1160 | # JR8ROI/4dFZM5sCsoYIDIDCCAxwGCSqGSIb3DQEJBjGCAw0wggMJAgEBMHcwYzEL 1161 | # MAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJE 1162 | # aWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBD 1163 | # QQIQC65mvFq6f5WHxvnpBOMzBDANBglghkgBZQMEAgEFAKBpMBgGCSqGSIb3DQEJ 1164 | # AzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTI1MDMyMjE0MzQxNlowLwYJ 1165 | # KoZIhvcNAQkEMSIEIIcxts0daxLBkpu4UPeOuR1N/Hrq8teCkTYj9wC9ScuRMA0G 1166 | # CSqGSIb3DQEBAQUABIICAEE0bBvkL2FtgHYGLmqgf5V0BJfHGUAVc6QLFfS9fdB6 1167 | # 4A+4+ZPlazbc6dW7mF5/0v9Aja6O4McYY1sQFZb0aHUJgJ9+tesx1stNriIUI61q 1168 | # cd0wimwUEKI0Ktmax2jbPS4tOM+gnzXUzWTJH+RcxE2EpQZ99MOHxsnlQCYT0X4n 1169 | # l9rdgvaaxmo7h9HV6LFPQueWRG0GFFPIxX8NWt0HO4c2RNUiUtR8hwA+MWw3hJog 1170 | # +SGjuDxFLtKJGfOeuNEtpgHLrUBSO+sgo4vWuvgT/m4GodTsfSepc8WymhADoloe 1171 | # TgIT9FIiC/bdhq+qDG7NM6IM9lrLDzVw3644EEAgmaIwQYJjSDPl5/5lzsCWUGmL 1172 | # M9Ikxa3wB6GxUFEyr0TcQMHBQkDremNsLjAewma+yksFcPiKBYYzbN+FuzQrIO0t 1173 | # K9CmgHQC2itgzg/uXESawVjvKZ5hKgOM5A9f7z44Fmp6JG/W1VhM+plCSfJ/akgM 1174 | # 6CPnxKvIE+wVck0Jnhd32nKfCnNBtkUtGFPYtqDHGn6y1K6FPUB/ix3gU1YwmTVh 1175 | # l0AfCJpwm2FJ4t6UmVcrOh/SXNLPl+j70T71eP007mJELJyS31Q8elVgmvQfBL78 1176 | # yY6BH0vdlXCQxPh87TFx+axG8nxA3Qdv9HAAn7Qfp9TtK5Ut0jpruYP76gBOzWK2 1177 | # SIG # End signature block 1178 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ashley How 4 | 5 | Copyright (c) 2018 Fredrik Wall 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. -------------------------------------------------------------------------------- /Private/Import-HtmlAgilityPack.ps1: -------------------------------------------------------------------------------- 1 | Function Import-HtmlAgilityPack { 2 | Try { 3 | Add-Type -AssemblyName 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' -ErrorAction Stop 4 | $dotNetTarget = "netstandard2" 5 | } 6 | Catch { 7 | $dotNetTarget = "net40-client" 8 | } 9 | 10 | $RootPath = Split-Path $PSScriptRoot -Parent 11 | $AssembliesToLoad = Get-ChildItem -Path "$RootPath\lib\*-$dotNetTarget.dll" 12 | 13 | Write-Verbose -Message "Loading Assemblies for .NET target: $dotNetTarget" 14 | Add-Type -Path $AssembliesToLoad.fullname -ErrorAction Stop 15 | } 16 | 17 | Import-HtmlAgilityPack 18 | # SIG # Begin signature block 19 | # MIImcgYJKoZIhvcNAQcCoIImYzCCJl8CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB 20 | # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR 21 | # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUm9+7bimqkyEVgKXmfUNTm8Wa 22 | # 7ZCggiAtMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B 23 | # AQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD 24 | # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk 25 | # IElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQsw 26 | # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu 27 | # ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw 28 | # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz 29 | # 7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS 30 | # 5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7 31 | # bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfI 32 | # SKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jH 33 | # trHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14 34 | # Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2 35 | # h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt 36 | # 6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPR 37 | # iQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ER 38 | # ElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4K 39 | # Jpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAd 40 | # BgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SS 41 | # y4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAk 42 | # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAC 43 | # hjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS 44 | # b290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 45 | # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRV 46 | # HSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyh 47 | # hyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO 48 | # 0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo 49 | # 8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++h 50 | # UD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5x 51 | # aiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMIIGYzCCBEug 52 | # AwIBAgIQeAuTgzemd0ILREkKU+Yq2jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQG 53 | # EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMSQwIgYDVQQD 54 | # ExtDZXJ0dW0gQ29kZSBTaWduaW5nIDIwMjEgQ0EwHhcNMjQwNDExMDYwMzIxWhcN 55 | # MjUwNDExMDYwMzIwWjCBiDELMAkGA1UEBhMCR0IxDzANBgNVBAgMBkRvcnNldDEU 56 | # MBIGA1UEBwwLQk9VUk5FTU9VVEgxHjAcBgNVBAoMFU9wZW4gU291cmNlIERldmVs 57 | # b3BlcjEyMDAGA1UEAwwpT3BlbiBTb3VyY2UgRGV2ZWxvcGVyLCBBU0hMRVkgTUlD 58 | # SEFFTCBIT1cwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDpmsgFPzl4 59 | # 7W61kLLEp5ljxHC0ZZDti0+DL2JSAac1+bQW24vSjg4ABHhRB5CDKBuwVe2h0l+G 60 | # mEZHhKc9cz/RB+hUIJycd5Qx6VzsI1KJ0heEECm+oo3rywyqrd9RovkhkU2X29cR 61 | # UAa9SWZJJ2+/ImyzfyxzR+u0DD17BucHXWylQB2HGFCcX3kYUmgyZ/ANrgTvetW+ 62 | # n91OLxquC5+Nslh4MhbQAnItX79qrFLODd05S3SpQvdti16WGcRwXka4t5zdAMf6 63 | # v3c8ThHKPm/1TsyWsYAUMYJ9C0sNt+QYKNYHRX7DuA1OJBngAyGggtaXmqEpPBX2 64 | # SkDJ0uOeVDoJEOsxNydGZYPgvkIzsyF8YmEzkPK5x5elglYI0wfGwaMKshVbszj5 65 | # KXIPogeF/0vrEi8iIEd+Ro3ZY8ul+TliYf6P55tl3VCuKHDbzcYCtOXURmAPGwxC 66 | # 9wVvTr946eJr+emejOxg4/BZw5Q5GD6Qr8wwyodqholbzp8bfjTFmC8CAwEAAaOC 67 | # AXgwggF0MAwGA1UdEwEB/wQCMAAwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2Nj 68 | # c2NhMjAyMS5jcmwuY2VydHVtLnBsL2Njc2NhMjAyMS5jcmwwcwYIKwYBBQUHAQEE 69 | # ZzBlMCwGCCsGAQUFBzABhiBodHRwOi8vY2NzY2EyMDIxLm9jc3AtY2VydHVtLmNv 70 | # bTA1BggrBgEFBQcwAoYpaHR0cDovL3JlcG9zaXRvcnkuY2VydHVtLnBsL2Njc2Nh 71 | # MjAyMS5jZXIwHwYDVR0jBBgwFoAU3XRdTADbe5+gdMqxbvc8wDLAcM0wHQYDVR0O 72 | # BBYEFB7BnDzi+HIrft6IpueXUsx5LcgwMEsGA1UdIAREMEIwCAYGZ4EMAQQBMDYG 73 | # CyqEaAGG9ncCBQEEMCcwJQYIKwYBBQUHAgEWGWh0dHBzOi8vd3d3LmNlcnR1bS5w 74 | # bC9DUFMwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDgYDVR0PAQH/BAQDAgeAMA0GCSqG 75 | # SIb3DQEBCwUAA4ICAQBO5qPmZq+cztnjKtz9DyVBkZGaHj/TmfIZHrYfeQ0zdEVL 76 | # EszgokLuqNDdk0odEUHiockPB2dQn60oE3rNs+Wb1ZLLT18VoQTV0saMD3GiNzil 77 | # ejD4nIrhQ+vt0auxCvzBS8cQd24ePmjTqcIkL/u07xGhtT3LpUHUuHknUcEFjgs0 78 | # bUpGR5bofW8B9ZSC31g2i5PKZH8PUgOrTvg8oaMQYWyduKFnW8JRRGqypjUIFDE0 79 | # N224ox/U6GqqIl2cuC87H7WrHPEO6VjqSOx0PgybhSggGDKRNk9UQN1R45K/NCcw 80 | # 5+sIA1pjTZHnMhIJdxamhXiNq2S0U3LRVLSs1/BuXGENFWUraE4c51kDCiBPpGus 81 | # olI7/LLF3PIyYopyAWOGw0R7snlT+HJbfI7P6ObfYzzmIMdrKSaBkNtautcRYcIT 82 | # HAmbUAVplnpexQXXapSqxUfrPXWZk7xRLSXXqn915NbAoofVrTuLNXbv437KmoaN 83 | # p2J23oE7KzqdkoZ9SO4+8K+XKoEqBrPyxNB/i5UIId1Rsu5GE453usJf7zgsz4Ib 84 | # T8MQXjPq0WageEH3cL3qoPGBVbD++hLCJhqHPFJfM3zqxz4xZIRm7dY7GmcVc3Qq 85 | # H0biPnYkTfe8fwrT/IpEmVPdDnUSM92MhV25HV4CYU5LAISU1B070DMFAGc1uTCC 86 | # Bq4wggSWoAMCAQICEAc2N7ckVHzYR6z9KGYqXlswDQYJKoZIhvcNAQELBQAwYjEL 87 | # MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 88 | # LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0 89 | # MB4XDTIyMDMyMzAwMDAwMFoXDTM3MDMyMjIzNTk1OVowYzELMAkGA1UEBhMCVVMx 90 | # FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVz 91 | # dGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTCCAiIwDQYJKoZI 92 | # hvcNAQEBBQADggIPADCCAgoCggIBAMaGNQZJs8E9cklRVcclA8TykTepl1Gh1tKD 93 | # 0Z5Mom2gsMyD+Vr2EaFEFUJfpIjzaPp985yJC3+dH54PMx9QEwsmc5Zt+FeoAn39 94 | # Q7SE2hHxc7Gz7iuAhIoiGN/r2j3EF3+rGSs+QtxnjupRPfDWVtTnKC3r07G1decf 95 | # BmWNlCnT2exp39mQh0YAe9tEQYncfGpXevA3eZ9drMvohGS0UvJ2R/dhgxndX7RU 96 | # CyFobjchu0CsX7LeSn3O9TkSZ+8OpWNs5KbFHc02DVzV5huowWR0QKfAcsW6Th+x 97 | # tVhNef7Xj3OTrCw54qVI1vCwMROpVymWJy71h6aPTnYVVSZwmCZ/oBpHIEPjQ2OA 98 | # e3VuJyWQmDo4EbP29p7mO1vsgd4iFNmCKseSv6De4z6ic/rnH1pslPJSlRErWHRA 99 | # KKtzQ87fSqEcazjFKfPKqpZzQmiftkaznTqj1QPgv/CiPMpC3BhIfxQ0z9JMq++b 100 | # Pf4OuGQq+nUoJEHtQr8FnGZJUlD0UfM2SU2LINIsVzV5K6jzRWC8I41Y99xh3pP+ 101 | # OcD5sjClTNfpmEpYPtMDiP6zj9NeS3YSUZPJjAw7W4oiqMEmCPkUEBIDfV8ju2Tj 102 | # Y+Cm4T72wnSyPx4JduyrXUZ14mCjWAkBKAAOhFTuzuldyF4wEr1GnrXTdrnSDmuZ 103 | # DNIztM2xAgMBAAGjggFdMIIBWTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW 104 | # BBS6FtltTYUvcyl2mi91jGogj57IbzAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/ 105 | # 57qYrhwPTzAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwdwYI 106 | # KwYBBQUHAQEEazBpMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j 107 | # b20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdp 108 | # Q2VydFRydXN0ZWRSb290RzQuY3J0MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9j 109 | # cmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3JsMCAGA1Ud 110 | # IAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEA 111 | # fVmOwJO2b5ipRCIBfmbW2CFC4bAYLhBNE88wU86/GPvHUF3iSyn7cIoNqilp/GnB 112 | # zx0H6T5gyNgL5Vxb122H+oQgJTQxZ822EpZvxFBMYh0MCIKoFr2pVs8Vc40BIiXO 113 | # lWk/R3f7cnQU1/+rT4osequFzUNf7WC2qk+RZp4snuCKrOX9jLxkJodskr2dfNBw 114 | # CnzvqLx1T7pa96kQsl3p/yhUifDVinF2ZdrM8HKjI/rAJ4JErpknG6skHibBt94q 115 | # 6/aesXmZgaNWhqsKRcnfxI2g55j7+6adcq/Ex8HBanHZxhOACcS2n82HhyS7T6NJ 116 | # uXdmkfFynOlLAlKnN36TU6w7HQhJD5TNOXrd/yVjmScsPT9rp/Fmw0HNT7ZAmyEh 117 | # QNC3EyTN3B14OuSereU0cZLXJmvkOHOrpgFPvT87eK1MrfvElXvtCl8zOYdBeHo4 118 | # 6Zzh3SP9HSjTx/no8Zhf+yvYfvJGnXUsHicsJttvFXseGYs2uJPU5vIXmVnKcPA3 119 | # v5gA3yAWTyf7YGcWoWa63VXAOimGsJigK+2VQbc61RWYMbRiCQ8KvYHZE/6/pNHz 120 | # V9m8BPqC3jLfBInwAM1dwvnQI38AC+R2AibZ8GV2QqYphwlHK+Z/GqSFD/yYlvZV 121 | # VCsfgPrA8g4r5db7qS9EFUrnEw4d2zc4GqEr9u3WfPwwgga5MIIEoaADAgECAhEA 122 | # maOACiZVO2Wr3G6EprPqOTANBgkqhkiG9w0BAQwFADCBgDELMAkGA1UEBhMCUEwx 123 | # IjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNl 124 | # cnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRy 125 | # dXN0ZWQgTmV0d29yayBDQSAyMB4XDTIxMDUxOTA1MzIxOFoXDTM2MDUxODA1MzIx 126 | # OFowVjELMAkGA1UEBhMCUEwxITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMg 127 | # Uy5BLjEkMCIGA1UEAxMbQ2VydHVtIENvZGUgU2lnbmluZyAyMDIxIENBMIICIjAN 128 | # BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnSPPBDAjO8FGLOczcz5jXXp1ur5c 129 | # Tbq96y34vuTmflN4mSAfgLKTvggv24/rWiVGzGxT9YEASVMw1Aj8ewTS4IndU8s7 130 | # VS5+djSoMcbvIKck6+hI1shsylP4JyLvmxwLHtSworV9wmjhNd627h27a8RdrT1P 131 | # H9ud0IF+njvMk2xqbNTIPsnWtw3E7DmDoUmDQiYi/ucJ42fcHqBkbbxYDB7SYOou 132 | # u9Tj1yHIohzuC8KNqfcYf7Z4/iZgkBJ+UFNDcc6zokZ2uJIxWgPWXMEmhu1gMXgv 133 | # 8aGUsRdaCtVD2bSlbfsq7BiqljjaCun+RJgTgFRCtsuAEw0pG9+FA+yQN9n/kZtM 134 | # LK+Wo837Q4QOZgYqVWQ4x6cM7/G0yswg1ElLlJj6NYKLw9EcBXE7TF3HybZtYvj9 135 | # lDV2nT8mFSkcSkAExzd4prHwYjUXTeZIlVXqj+eaYqoMTpMrfh5MCAOIG5knN4Q/ 136 | # JHuurfTI5XDYO962WZayx7ACFf5ydJpoEowSP07YaBiQ8nXpDkNrUA9g7qf/rCkK 137 | # bWpQ5boufUnq1UiYPIAHlezf4muJqxqIns/kqld6JVX8cixbd6PzkDpwZo4SlADa 138 | # Ci2JSplKShBSND36E/ENVv8urPS0yOnpG4tIoBGxVCARPCg1BnyMJ4rBJAcOSnAW 139 | # d18Jx5n858JSqPECAwEAAaOCAVUwggFRMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O 140 | # BBYEFN10XUwA23ufoHTKsW73PMAywHDNMB8GA1UdIwQYMBaAFLahVDkCw6A/joq8 141 | # +tT4HKbROg79MA4GA1UdDwEB/wQEAwIBBjATBgNVHSUEDDAKBggrBgEFBQcDAzAw 142 | # BgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vY3JsLmNlcnR1bS5wbC9jdG5jYTIuY3Js 143 | # MGwGCCsGAQUFBwEBBGAwXjAoBggrBgEFBQcwAYYcaHR0cDovL3N1YmNhLm9jc3At 144 | # Y2VydHVtLmNvbTAyBggrBgEFBQcwAoYmaHR0cDovL3JlcG9zaXRvcnkuY2VydHVt 145 | # LnBsL2N0bmNhMi5jZXIwOQYDVR0gBDIwMDAuBgRVHSAAMCYwJAYIKwYBBQUHAgEW 146 | # GGh0dHA6Ly93d3cuY2VydHVtLnBsL0NQUzANBgkqhkiG9w0BAQwFAAOCAgEAdYhY 147 | # D+WPUCiaU58Q7EP89DttyZqGYn2XRDhJkL6P+/T0IPZyxfxiXumYlARMgwRzLRUS 148 | # tJl490L94C9LGF3vjzzH8Jq3iR74BRlkO18J3zIdmCKQa5LyZ48IfICJTZVJeChD 149 | # UyuQy6rGDxLUUAsO0eqeLNhLVsgw6/zOfImNlARKn1FP7o0fTbj8ipNGxHBIutiR 150 | # sWrhWM2f8pXdd3x2mbJCKKtl2s42g9KUJHEIiLni9ByoqIUul4GblLQigO0ugh7b 151 | # WRLDm0CdY9rNLqyA3ahe8WlxVWkxyrQLjH8ItI17RdySaYayX3PhRSC4Am1/7mAT 152 | # wZWwSD+B7eMcZNhpn8zJ+6MTyE6YoEBSRVrs0zFFIHUR08Wk0ikSf+lIe5Iv6RY3 153 | # /bFAEloMU+vUBfSouCReZwSLo8WdrDlPXtR0gicDnytO7eZ5827NS2x7gCBibESY 154 | # kOh1/w1tVxTpV2Na3PR7nxYVlPu1JPoRZCbH86gc96UTvuWiOruWmyOEMLOGGniR 155 | # +x+zPF/2DaGgK2W1eEJfo2qyrBNPvF7wuAyQfiFXLwvWHamoYtPZo0LHuH8X3n9C 156 | # +xN4YaNjt2ywzOr+tKyEVAotnyU9vyEVOaIYMk3IeBrmFnn0gbKeTTyYeEEUz/Qw 157 | # t4HOUBCrW602NCmvO1nm+/80nLy5r0AZvCQxaQ4wggbCMIIEqqADAgECAhAFRK/z 158 | # lJ0IOaa/2z9f5WEWMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcwFQYD 159 | # VQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBH 160 | # NCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMjMwNzE0MDAwMDAw 161 | # WhcNMzQxMDEzMjM1OTU5WjBIMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNl 162 | # cnQsIEluYy4xIDAeBgNVBAMTF0RpZ2lDZXJ0IFRpbWVzdGFtcCAyMDIzMIICIjAN 163 | # BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAo1NFhx2DjlusPlSzI+DPn9fl0udd 164 | # oQ4J3C9Io5d6OyqcZ9xiFVjBqZMRp82qsmrdECmKHmJjadNYnDVxvzqX65RQjxwg 165 | # 6seaOy+WZuNp52n+W8PWKyAcwZeUtKVQgfLPywemMGjKg0La/H8JJJSkghraarrY 166 | # O8pd3hkYhftF6g1hbJ3+cV7EBpo88MUueQ8bZlLjyNY+X9pD04T10Mf2SC1eRXWW 167 | # df7dEKEbg8G45lKVtUfXeCk5a+B4WZfjRCtK1ZXO7wgX6oJkTf8j48qG7rSkIWRw 168 | # 69XloNpjsy7pBe6q9iT1HbybHLK3X9/w7nZ9MZllR1WdSiQvrCuXvp/k/XtzPjLu 169 | # UjT71Lvr1KAsNJvj3m5kGQc3AZEPHLVRzapMZoOIaGK7vEEbeBlt5NkP4FhB+9ix 170 | # LOFRr7StFQYU6mIIE9NpHnxkTZ0P387RXoyqq1AVybPKvNfEO2hEo6U7Qv1zfe7d 171 | # Cv95NBB+plwKWEwAPoVpdceDZNZ1zY8SdlalJPrXxGshuugfNJgvOuprAbD3+yqG 172 | # 7HtSOKmYCaFxsmxxrz64b5bV4RAT/mFHCoz+8LbH1cfebCTwv0KCyqBxPZySkwS0 173 | # aXAnDU+3tTbRyV8IpHCj7ArxES5k4MsiK8rxKBMhSVF+BmbTO77665E42FEHypS3 174 | # 4lCh8zrTioPLQHsCAwEAAaOCAYswggGHMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMB 175 | # Af8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMCAGA1UdIAQZMBcwCAYGZ4EM 176 | # AQQCMAsGCWCGSAGG/WwHATAfBgNVHSMEGDAWgBS6FtltTYUvcyl2mi91jGogj57I 177 | # bzAdBgNVHQ4EFgQUpbbvE+fvzdBkodVWqWUxo97V40kwWgYDVR0fBFMwUTBPoE2g 178 | # S4ZJaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNB 179 | # NDA5NlNIQTI1NlRpbWVTdGFtcGluZ0NBLmNybDCBkAYIKwYBBQUHAQEEgYMwgYAw 180 | # JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBYBggrBgEFBQcw 181 | # AoZMaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0 182 | # UlNBNDA5NlNIQTI1NlRpbWVTdGFtcGluZ0NBLmNydDANBgkqhkiG9w0BAQsFAAOC 183 | # AgEAgRrW3qCptZgXvHCNT4o8aJzYJf/LLOTN6l0ikuyMIgKpuM+AqNnn48XtJoKK 184 | # cS8Y3U623mzX4WCcK+3tPUiOuGu6fF29wmE3aEl3o+uQqhLXJ4Xzjh6S2sJAOJ9d 185 | # yKAuJXglnSoFeoQpmLZXeY/bJlYrsPOnvTcM2Jh2T1a5UsK2nTipgedtQVyMadG5 186 | # K8TGe8+c+njikxp2oml101DkRBK+IA2eqUTQ+OVJdwhaIcW0z5iVGlS6ubzBaRm6 187 | # zxbygzc0brBBJt3eWpdPM43UjXd9dUWhpVgmagNF3tlQtVCMr1a9TMXhRsUo063n 188 | # QwBw3syYnhmJA+rUkTfvTVLzyWAhxFZH7doRS4wyw4jmWOK22z75X7BC1o/jF5HR 189 | # qsBV44a/rCcsQdCaM0qoNtS5cpZ+l3k4SF/Kwtw9Mt911jZnWon49qfH5U81PAC9 190 | # vpwqbHkB3NpE5jreODsHXjlY9HxzMVWggBHLFAx+rrz+pOt5Zapo1iLKO+uagjVX 191 | # KBbLafIymrLS2Dq4sUaGa7oX/cR3bBVsrquvczroSUa31X/MtjjA2Owc9bahuEMs 192 | # 305MfR5ocMB3CtQC4Fxguyj/OOVSWtasFyIjTvTs0xf7UGv/B3cfcZdEQcm4RtNs 193 | # MnxYL2dHZeUbc7aZ+WssBkbvQR7w8F/g29mtkIBEr4AQQYoxggWvMIIFqwIBATBq 194 | # MFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMu 195 | # QS4xJDAiBgNVBAMTG0NlcnR1bSBDb2RlIFNpZ25pbmcgMjAyMSBDQQIQeAuTgzem 196 | # d0ILREkKU+Yq2jAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKA 197 | # ADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYK 198 | # KwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUfj5jibhkQ4hWE1daPtlp5LuZtQww 199 | # DQYJKoZIhvcNAQEBBQAEggGAnh4k4NzsMt/lb9WDebg9UCC+byZvP0T5ijlZBhmK 200 | # 0O32znPsaPd619C/mpzr2KipZwFWQt1t5yD6DHKNlRxfvcSIEz9j3vF+3+soqMFW 201 | # P61ABjYMMVz6Y2wNwCGR58J/c6/iJ3EKeSagANpwUZlpLp+iPp3S7pSh3On5em45 202 | # JY2/wVE1eazGomte2elO3qwUgQ0KqZxfLlOnI0Y2Ech9CwZFug1JV8fvjykCqhvN 203 | # SqiiGGA0zJxmJ5rjeToAbCdI2x6ENUQzt4/t0BD5n/05TvhQhbkDwF9BgJ5szOP6 204 | # r4NrFu4oi+74SULtObG3IKS5RG+E4NKg9fUzy0pvpc17LXkmnZNqNdVB8/t3tJlv 205 | # MbWyuenyqTwvHcz0S+g12uu6+e3GPicuj+pr6JCQxLALSX30esxX1SZKEI29l+mC 206 | # OdJndk8nW1MP7y4pDQ06KaFgQh2B3GW8LGejlb5iWSq+u/S4M0aA+fM4hPJq21uj 207 | # 0TTz2udz0dV/ceHtVmIWLot0oYIDIDCCAxwGCSqGSIb3DQEJBjGCAw0wggMJAgEB 208 | # MHcwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYD 209 | # VQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFt 210 | # cGluZyBDQQIQBUSv85SdCDmmv9s/X+VhFjANBglghkgBZQMEAgEFAKBpMBgGCSqG 211 | # SIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTI0MDQyNDIyMDkx 212 | # M1owLwYJKoZIhvcNAQkEMSIEIPg8iErLWNwSeE/KNCJ+JbMgQHrTANyexU+X8+hb 213 | # wCOvMA0GCSqGSIb3DQEBAQUABIICAC8bzeqcQCIZsm8rIowuGaEUCmJ5jXZin8EA 214 | # S0nWLKpzq63dw3ldNffrYaC+28cCz6kFcXRDr4tM9a9oneqbQTEgNiP2PqBdLRTt 215 | # 2WPBGdYaThkrSKg0UobzfV13dk0I9lwwfJhCINT+yoM8PseM9Nmc+IM7PdAGwMHs 216 | # M7TMEuqrL8RCHY2+eKmxBXZhTPXM90jj0otnA18taHPojJk9DvhkngeuYQt3ptHe 217 | # OKEJI5JklBSRVkA1qnVJMBXN81q+11WxvcB11ZYKn6QhhOMQa6iD/qX3+qJJLivJ 218 | # /2OfiixqYy+CZyktkCXAH9iucYBjV+HmdoedgYZKhp0i3wVeQaHPFFIVxvQX1OzU 219 | # 4/yqcRhRUM8wlgg6nAKrI8aZksfHRc46FfYx7bOYB1lvSAf/xp7wRRcioGuk9Saq 220 | # VAHt51N7rSKv60jfq9GuWj/mQupAjanLD/ziEnMMrXrSNWTuM3eXe86BOzuZ5mh7 221 | # FX4DqLMxOQtcBh08pQ6uUOkOmU8qmLoGUc7kJGcDE+JUQMo8EGawjYEr1BcxvKcG 222 | # jTuyA/w1+wFRegThbPorafRZvcfTi2zdtMQad4mrnuj2Mws2YsfLl7HDRpXGWP55 223 | # r8kSiGwpa5+xzn+5uyTxti4hkfbnL2bwIo9H2fg46vo1oSWkr17K5/wwvD2S7QkU 224 | # amPOP//2 225 | # SIG # End signature block 226 | -------------------------------------------------------------------------------- /Public/Get-CurrentOSBuild.ps1: -------------------------------------------------------------------------------- 1 | Function Get-CurrentOSBuild { 2 | <# 3 | .SYNOPSIS 4 | Gets the currently installed OS Build release information. Supports Windows 10 and Windows Server 2016 onwards. Supports Hotpatch on Windows 11 and Windows Server 2022. 5 | .DESCRIPTION 6 | Installed OS Build number or detailed information (Version, Build, Availability date, Hotpatch, Preview, Out-of-band, Servicing option, KB article, KB URL and Catalog URL). 7 | .PARAMETER Detailed 8 | This parameter is optional. Returns detailed information about the installed OS Build. 9 | .EXAMPLE 10 | Get-CurrentOSBuild 11 | Show only the build number for the installed OS Build. 12 | .EXAMPLE 13 | Get-CurrentOSBuild -Detailed 14 | Show detailed information for the installed OS Build. 15 | #> 16 | 17 | Param( 18 | [CmdletBinding()] 19 | [Parameter(Mandatory = $false)] 20 | [Switch]$Detailed 21 | ) 22 | 23 | Function Get-Build { 24 | # Check for Windows 10 1507 as ReleaseId does not exist until 1511 25 | If ((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name CurrentBuild).CurrentBuild -eq "10240") { 26 | Return "1507" 27 | } 28 | Else { 29 | $ReleaseID = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name ReleaseId).ReleaseId 30 | If ($ReleaseID -eq '2009') { 31 | $DisplayVersion = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name DisplayVersion).DisplayVersion 32 | Return $DisplayVersion 33 | } 34 | Else { 35 | Return $ReleaseID 36 | } 37 | } 38 | } 39 | 40 | $CurrentBuild = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name CurrentBuild).CurrentBuild 41 | $UBR = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name UBR).UBR 42 | $CurrentOSBuild = $CurrentBuild + '.' + $UBR 43 | 44 | If ($Detailed -eq $true) { 45 | Try { 46 | $GetOSCaption = (Get-CIMInstance Win32_OperatingSystem).Caption 47 | } 48 | Catch { 49 | Throw "Get-CurrentOSBuild: Unable to get operating system caption. Error: $($_.Exception.Message)" 50 | } 51 | 52 | If ($GetOSCaption -match "Windows 10") { 53 | $DetectedOS = "Win10" 54 | } 55 | ElseIf ($GetOSCaption -match "Windows 11") { 56 | If ((Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\PolicyManager\current\device\Update" -Name "AllowRebootlessUpdates" -ErrorAction SilentlyContinue).AllowRebootlessUpdates -eq 1) { 57 | $DetectedOS = "Win11Hotpatch" 58 | } 59 | Else { 60 | $DetectedOS = "Win11" 61 | } 62 | } 63 | ElseIf ($GetOSCaption -match "Server 2016") { 64 | $DetectedOS = "Server2016" 65 | } 66 | ElseIf ($GetOSCaption -match "Server 2019") { 67 | $DetectedOS = "Server2019" 68 | } 69 | ElseIf ($GetOSCaption -match "Server 2022") { 70 | If (Get-HotFix -Id KB5003508 -ErrorAction SilentlyContinue) { 71 | $DetectedOS = "Server2022Hotpatch" 72 | $FallBackOS = "Server2022" 73 | } 74 | Else { 75 | $DetectedOS = "Server2022" 76 | } 77 | } 78 | ElseIf ($GetOSCaption -match "Server 2025") { 79 | If (($null -ne ((New-Object -ComObject Microsoft.Update.Session).CreateUpdateSearcher().Search("IsInstalled=1").Updates | Where-Object { $_.Title -like "*Hotpatch*" } | Select-Object -First 1))) { 80 | $DetectedOS = "Server2025Hotpatch" 81 | $FallBackOS = "Server2025" 82 | } 83 | Else { 84 | $DetectedOS = "Server2025" 85 | } 86 | } 87 | ElseIf ($GetOSCaption -match "Windows Server Standard" -or $GetOSCaption -match "Windows Server Datacenter") { 88 | $DetectedOS = "ServerSAC" 89 | } 90 | Else { 91 | Throw "Get-CurrentOSBuild: Unable to detect operating system. OS Caption: $GetOSCaption, Detected OS: $DetectedOS" 92 | } 93 | 94 | # Hotpatch OS 95 | If ($FallBackOS) { 96 | $Results = Get-LatestOSBuild -OSName $DetectedOS -OSversion $(Get-Build) -LatestReleases 1000 | Where-Object -Property Build -eq $CurrentOSBuild 97 | # Handle Hotpatch capable OS thats is not using hotpatch updates 98 | If (!$Results) { 99 | $Results = Get-LatestOSBuild -OSName $FallBackOS -OSversion $(Get-Build) -LatestReleases 1000 | Where-Object -Property Build -eq $CurrentOSBuild 100 | } 101 | $Results 102 | } 103 | # All other OS 104 | Else { 105 | Get-LatestOSBuild -OSName $DetectedOS -OSversion $(Get-Build) -LatestReleases 1000 | Where-Object -Property Build -eq $CurrentOSBuild 106 | } 107 | } 108 | Else { 109 | Return $CurrentOSBuild 110 | } 111 | } 112 | # SIG # Begin signature block 113 | # MIImbAYJKoZIhvcNAQcCoIImXTCCJlkCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB 114 | # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR 115 | # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQURWesXTOtphJu/Z+y0O/CI3mO 116 | # F/SggiAnMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B 117 | # AQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD 118 | # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk 119 | # IElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQsw 120 | # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu 121 | # ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw 122 | # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz 123 | # 7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS 124 | # 5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7 125 | # bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfI 126 | # SKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jH 127 | # trHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14 128 | # Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2 129 | # h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt 130 | # 6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPR 131 | # iQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ER 132 | # ElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4K 133 | # Jpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAd 134 | # BgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SS 135 | # y4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAk 136 | # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAC 137 | # hjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS 138 | # b290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 139 | # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRV 140 | # HSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyh 141 | # hyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO 142 | # 0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo 143 | # 8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++h 144 | # UD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5x 145 | # aiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMIIGYzCCBEug 146 | # AwIBAgIQeAuTgzemd0ILREkKU+Yq2jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQG 147 | # EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMSQwIgYDVQQD 148 | # ExtDZXJ0dW0gQ29kZSBTaWduaW5nIDIwMjEgQ0EwHhcNMjQwNDExMDYwMzIxWhcN 149 | # MjUwNDExMDYwMzIwWjCBiDELMAkGA1UEBhMCR0IxDzANBgNVBAgMBkRvcnNldDEU 150 | # MBIGA1UEBwwLQk9VUk5FTU9VVEgxHjAcBgNVBAoMFU9wZW4gU291cmNlIERldmVs 151 | # b3BlcjEyMDAGA1UEAwwpT3BlbiBTb3VyY2UgRGV2ZWxvcGVyLCBBU0hMRVkgTUlD 152 | # SEFFTCBIT1cwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDpmsgFPzl4 153 | # 7W61kLLEp5ljxHC0ZZDti0+DL2JSAac1+bQW24vSjg4ABHhRB5CDKBuwVe2h0l+G 154 | # mEZHhKc9cz/RB+hUIJycd5Qx6VzsI1KJ0heEECm+oo3rywyqrd9RovkhkU2X29cR 155 | # UAa9SWZJJ2+/ImyzfyxzR+u0DD17BucHXWylQB2HGFCcX3kYUmgyZ/ANrgTvetW+ 156 | # n91OLxquC5+Nslh4MhbQAnItX79qrFLODd05S3SpQvdti16WGcRwXka4t5zdAMf6 157 | # v3c8ThHKPm/1TsyWsYAUMYJ9C0sNt+QYKNYHRX7DuA1OJBngAyGggtaXmqEpPBX2 158 | # SkDJ0uOeVDoJEOsxNydGZYPgvkIzsyF8YmEzkPK5x5elglYI0wfGwaMKshVbszj5 159 | # KXIPogeF/0vrEi8iIEd+Ro3ZY8ul+TliYf6P55tl3VCuKHDbzcYCtOXURmAPGwxC 160 | # 9wVvTr946eJr+emejOxg4/BZw5Q5GD6Qr8wwyodqholbzp8bfjTFmC8CAwEAAaOC 161 | # AXgwggF0MAwGA1UdEwEB/wQCMAAwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2Nj 162 | # c2NhMjAyMS5jcmwuY2VydHVtLnBsL2Njc2NhMjAyMS5jcmwwcwYIKwYBBQUHAQEE 163 | # ZzBlMCwGCCsGAQUFBzABhiBodHRwOi8vY2NzY2EyMDIxLm9jc3AtY2VydHVtLmNv 164 | # bTA1BggrBgEFBQcwAoYpaHR0cDovL3JlcG9zaXRvcnkuY2VydHVtLnBsL2Njc2Nh 165 | # MjAyMS5jZXIwHwYDVR0jBBgwFoAU3XRdTADbe5+gdMqxbvc8wDLAcM0wHQYDVR0O 166 | # BBYEFB7BnDzi+HIrft6IpueXUsx5LcgwMEsGA1UdIAREMEIwCAYGZ4EMAQQBMDYG 167 | # CyqEaAGG9ncCBQEEMCcwJQYIKwYBBQUHAgEWGWh0dHBzOi8vd3d3LmNlcnR1bS5w 168 | # bC9DUFMwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDgYDVR0PAQH/BAQDAgeAMA0GCSqG 169 | # SIb3DQEBCwUAA4ICAQBO5qPmZq+cztnjKtz9DyVBkZGaHj/TmfIZHrYfeQ0zdEVL 170 | # EszgokLuqNDdk0odEUHiockPB2dQn60oE3rNs+Wb1ZLLT18VoQTV0saMD3GiNzil 171 | # ejD4nIrhQ+vt0auxCvzBS8cQd24ePmjTqcIkL/u07xGhtT3LpUHUuHknUcEFjgs0 172 | # bUpGR5bofW8B9ZSC31g2i5PKZH8PUgOrTvg8oaMQYWyduKFnW8JRRGqypjUIFDE0 173 | # N224ox/U6GqqIl2cuC87H7WrHPEO6VjqSOx0PgybhSggGDKRNk9UQN1R45K/NCcw 174 | # 5+sIA1pjTZHnMhIJdxamhXiNq2S0U3LRVLSs1/BuXGENFWUraE4c51kDCiBPpGus 175 | # olI7/LLF3PIyYopyAWOGw0R7snlT+HJbfI7P6ObfYzzmIMdrKSaBkNtautcRYcIT 176 | # HAmbUAVplnpexQXXapSqxUfrPXWZk7xRLSXXqn915NbAoofVrTuLNXbv437KmoaN 177 | # p2J23oE7KzqdkoZ9SO4+8K+XKoEqBrPyxNB/i5UIId1Rsu5GE453usJf7zgsz4Ib 178 | # T8MQXjPq0WageEH3cL3qoPGBVbD++hLCJhqHPFJfM3zqxz4xZIRm7dY7GmcVc3Qq 179 | # H0biPnYkTfe8fwrT/IpEmVPdDnUSM92MhV25HV4CYU5LAISU1B070DMFAGc1uTCC 180 | # Bq4wggSWoAMCAQICEAc2N7ckVHzYR6z9KGYqXlswDQYJKoZIhvcNAQELBQAwYjEL 181 | # MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 182 | # LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0 183 | # MB4XDTIyMDMyMzAwMDAwMFoXDTM3MDMyMjIzNTk1OVowYzELMAkGA1UEBhMCVVMx 184 | # FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVz 185 | # dGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTCCAiIwDQYJKoZI 186 | # hvcNAQEBBQADggIPADCCAgoCggIBAMaGNQZJs8E9cklRVcclA8TykTepl1Gh1tKD 187 | # 0Z5Mom2gsMyD+Vr2EaFEFUJfpIjzaPp985yJC3+dH54PMx9QEwsmc5Zt+FeoAn39 188 | # Q7SE2hHxc7Gz7iuAhIoiGN/r2j3EF3+rGSs+QtxnjupRPfDWVtTnKC3r07G1decf 189 | # BmWNlCnT2exp39mQh0YAe9tEQYncfGpXevA3eZ9drMvohGS0UvJ2R/dhgxndX7RU 190 | # CyFobjchu0CsX7LeSn3O9TkSZ+8OpWNs5KbFHc02DVzV5huowWR0QKfAcsW6Th+x 191 | # tVhNef7Xj3OTrCw54qVI1vCwMROpVymWJy71h6aPTnYVVSZwmCZ/oBpHIEPjQ2OA 192 | # e3VuJyWQmDo4EbP29p7mO1vsgd4iFNmCKseSv6De4z6ic/rnH1pslPJSlRErWHRA 193 | # KKtzQ87fSqEcazjFKfPKqpZzQmiftkaznTqj1QPgv/CiPMpC3BhIfxQ0z9JMq++b 194 | # Pf4OuGQq+nUoJEHtQr8FnGZJUlD0UfM2SU2LINIsVzV5K6jzRWC8I41Y99xh3pP+ 195 | # OcD5sjClTNfpmEpYPtMDiP6zj9NeS3YSUZPJjAw7W4oiqMEmCPkUEBIDfV8ju2Tj 196 | # Y+Cm4T72wnSyPx4JduyrXUZ14mCjWAkBKAAOhFTuzuldyF4wEr1GnrXTdrnSDmuZ 197 | # DNIztM2xAgMBAAGjggFdMIIBWTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW 198 | # BBS6FtltTYUvcyl2mi91jGogj57IbzAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/ 199 | # 57qYrhwPTzAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwdwYI 200 | # KwYBBQUHAQEEazBpMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j 201 | # b20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdp 202 | # Q2VydFRydXN0ZWRSb290RzQuY3J0MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9j 203 | # cmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3JsMCAGA1Ud 204 | # IAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEA 205 | # fVmOwJO2b5ipRCIBfmbW2CFC4bAYLhBNE88wU86/GPvHUF3iSyn7cIoNqilp/GnB 206 | # zx0H6T5gyNgL5Vxb122H+oQgJTQxZ822EpZvxFBMYh0MCIKoFr2pVs8Vc40BIiXO 207 | # lWk/R3f7cnQU1/+rT4osequFzUNf7WC2qk+RZp4snuCKrOX9jLxkJodskr2dfNBw 208 | # CnzvqLx1T7pa96kQsl3p/yhUifDVinF2ZdrM8HKjI/rAJ4JErpknG6skHibBt94q 209 | # 6/aesXmZgaNWhqsKRcnfxI2g55j7+6adcq/Ex8HBanHZxhOACcS2n82HhyS7T6NJ 210 | # uXdmkfFynOlLAlKnN36TU6w7HQhJD5TNOXrd/yVjmScsPT9rp/Fmw0HNT7ZAmyEh 211 | # QNC3EyTN3B14OuSereU0cZLXJmvkOHOrpgFPvT87eK1MrfvElXvtCl8zOYdBeHo4 212 | # 6Zzh3SP9HSjTx/no8Zhf+yvYfvJGnXUsHicsJttvFXseGYs2uJPU5vIXmVnKcPA3 213 | # v5gA3yAWTyf7YGcWoWa63VXAOimGsJigK+2VQbc61RWYMbRiCQ8KvYHZE/6/pNHz 214 | # V9m8BPqC3jLfBInwAM1dwvnQI38AC+R2AibZ8GV2QqYphwlHK+Z/GqSFD/yYlvZV 215 | # VCsfgPrA8g4r5db7qS9EFUrnEw4d2zc4GqEr9u3WfPwwgga5MIIEoaADAgECAhEA 216 | # maOACiZVO2Wr3G6EprPqOTANBgkqhkiG9w0BAQwFADCBgDELMAkGA1UEBhMCUEwx 217 | # IjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNl 218 | # cnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRy 219 | # dXN0ZWQgTmV0d29yayBDQSAyMB4XDTIxMDUxOTA1MzIxOFoXDTM2MDUxODA1MzIx 220 | # OFowVjELMAkGA1UEBhMCUEwxITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMg 221 | # Uy5BLjEkMCIGA1UEAxMbQ2VydHVtIENvZGUgU2lnbmluZyAyMDIxIENBMIICIjAN 222 | # BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnSPPBDAjO8FGLOczcz5jXXp1ur5c 223 | # Tbq96y34vuTmflN4mSAfgLKTvggv24/rWiVGzGxT9YEASVMw1Aj8ewTS4IndU8s7 224 | # VS5+djSoMcbvIKck6+hI1shsylP4JyLvmxwLHtSworV9wmjhNd627h27a8RdrT1P 225 | # H9ud0IF+njvMk2xqbNTIPsnWtw3E7DmDoUmDQiYi/ucJ42fcHqBkbbxYDB7SYOou 226 | # u9Tj1yHIohzuC8KNqfcYf7Z4/iZgkBJ+UFNDcc6zokZ2uJIxWgPWXMEmhu1gMXgv 227 | # 8aGUsRdaCtVD2bSlbfsq7BiqljjaCun+RJgTgFRCtsuAEw0pG9+FA+yQN9n/kZtM 228 | # LK+Wo837Q4QOZgYqVWQ4x6cM7/G0yswg1ElLlJj6NYKLw9EcBXE7TF3HybZtYvj9 229 | # lDV2nT8mFSkcSkAExzd4prHwYjUXTeZIlVXqj+eaYqoMTpMrfh5MCAOIG5knN4Q/ 230 | # JHuurfTI5XDYO962WZayx7ACFf5ydJpoEowSP07YaBiQ8nXpDkNrUA9g7qf/rCkK 231 | # bWpQ5boufUnq1UiYPIAHlezf4muJqxqIns/kqld6JVX8cixbd6PzkDpwZo4SlADa 232 | # Ci2JSplKShBSND36E/ENVv8urPS0yOnpG4tIoBGxVCARPCg1BnyMJ4rBJAcOSnAW 233 | # d18Jx5n858JSqPECAwEAAaOCAVUwggFRMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O 234 | # BBYEFN10XUwA23ufoHTKsW73PMAywHDNMB8GA1UdIwQYMBaAFLahVDkCw6A/joq8 235 | # +tT4HKbROg79MA4GA1UdDwEB/wQEAwIBBjATBgNVHSUEDDAKBggrBgEFBQcDAzAw 236 | # BgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vY3JsLmNlcnR1bS5wbC9jdG5jYTIuY3Js 237 | # MGwGCCsGAQUFBwEBBGAwXjAoBggrBgEFBQcwAYYcaHR0cDovL3N1YmNhLm9jc3At 238 | # Y2VydHVtLmNvbTAyBggrBgEFBQcwAoYmaHR0cDovL3JlcG9zaXRvcnkuY2VydHVt 239 | # LnBsL2N0bmNhMi5jZXIwOQYDVR0gBDIwMDAuBgRVHSAAMCYwJAYIKwYBBQUHAgEW 240 | # GGh0dHA6Ly93d3cuY2VydHVtLnBsL0NQUzANBgkqhkiG9w0BAQwFAAOCAgEAdYhY 241 | # D+WPUCiaU58Q7EP89DttyZqGYn2XRDhJkL6P+/T0IPZyxfxiXumYlARMgwRzLRUS 242 | # tJl490L94C9LGF3vjzzH8Jq3iR74BRlkO18J3zIdmCKQa5LyZ48IfICJTZVJeChD 243 | # UyuQy6rGDxLUUAsO0eqeLNhLVsgw6/zOfImNlARKn1FP7o0fTbj8ipNGxHBIutiR 244 | # sWrhWM2f8pXdd3x2mbJCKKtl2s42g9KUJHEIiLni9ByoqIUul4GblLQigO0ugh7b 245 | # WRLDm0CdY9rNLqyA3ahe8WlxVWkxyrQLjH8ItI17RdySaYayX3PhRSC4Am1/7mAT 246 | # wZWwSD+B7eMcZNhpn8zJ+6MTyE6YoEBSRVrs0zFFIHUR08Wk0ikSf+lIe5Iv6RY3 247 | # /bFAEloMU+vUBfSouCReZwSLo8WdrDlPXtR0gicDnytO7eZ5827NS2x7gCBibESY 248 | # kOh1/w1tVxTpV2Na3PR7nxYVlPu1JPoRZCbH86gc96UTvuWiOruWmyOEMLOGGniR 249 | # +x+zPF/2DaGgK2W1eEJfo2qyrBNPvF7wuAyQfiFXLwvWHamoYtPZo0LHuH8X3n9C 250 | # +xN4YaNjt2ywzOr+tKyEVAotnyU9vyEVOaIYMk3IeBrmFnn0gbKeTTyYeEEUz/Qw 251 | # t4HOUBCrW602NCmvO1nm+/80nLy5r0AZvCQxaQ4wgga8MIIEpKADAgECAhALrma8 252 | # Wrp/lYfG+ekE4zMEMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcwFQYD 253 | # VQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBH 254 | # NCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMjQwOTI2MDAwMDAw 255 | # WhcNMzUxMTI1MjM1OTU5WjBCMQswCQYDVQQGEwJVUzERMA8GA1UEChMIRGlnaUNl 256 | # cnQxIDAeBgNVBAMTF0RpZ2lDZXJ0IFRpbWVzdGFtcCAyMDI0MIICIjANBgkqhkiG 257 | # 9w0BAQEFAAOCAg8AMIICCgKCAgEAvmpzn/aVIauWMLpbbeZZo7Xo/ZEfGMSIO2qZ 258 | # 46XB/QowIEMSvgjEdEZ3v4vrrTHleW1JWGErrjOL0J4L0HqVR1czSzvUQ5xF7z4I 259 | # Qmn7dHY7yijvoQ7ujm0u6yXF2v1CrzZopykD07/9fpAT4BxpT9vJoJqAsP8YuhRv 260 | # flJ9YeHjes4fduksTHulntq9WelRWY++TFPxzZrbILRYynyEy7rS1lHQKFpXvo2G 261 | # ePfsMRhNf1F41nyEg5h7iOXv+vjX0K8RhUisfqw3TTLHj1uhS66YX2LZPxS4oaf3 262 | # 3rp9HlfqSBePejlYeEdU740GKQM7SaVSH3TbBL8R6HwX9QVpGnXPlKdE4fBIn5BB 263 | # FnV+KwPxRNUNK6lYk2y1WSKour4hJN0SMkoaNV8hyyADiX1xuTxKaXN12HgR+8Wu 264 | # lU2d6zhzXomJ2PleI9V2yfmfXSPGYanGgxzqI+ShoOGLomMd3mJt92nm7Mheng/T 265 | # BeSA2z4I78JpwGpTRHiT7yHqBiV2ngUIyCtd0pZ8zg3S7bk4QC4RrcnKJ3FbjyPA 266 | # GogmoiZ33c1HG93Vp6lJ415ERcC7bFQMRbxqrMVANiav1k425zYyFMyLNyE1QulQ 267 | # SgDpW9rtvVcIH7WvG9sqYup9j8z9J1XqbBZPJ5XLln8mS8wWmdDLnBHXgYly/p1D 268 | # hoQo5fkCAwEAAaOCAYswggGHMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAA 269 | # MBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsG 270 | # CWCGSAGG/WwHATAfBgNVHSMEGDAWgBS6FtltTYUvcyl2mi91jGogj57IbzAdBgNV 271 | # HQ4EFgQUn1csA3cOKBWQZqVjXu5Pkh92oFswWgYDVR0fBFMwUTBPoE2gS4ZJaHR0 272 | # cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5NlNI 273 | # QTI1NlRpbWVTdGFtcGluZ0NBLmNybDCBkAYIKwYBBQUHAQEEgYMwgYAwJAYIKwYB 274 | # BQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBYBggrBgEFBQcwAoZMaHR0 275 | # cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5 276 | # NlNIQTI1NlRpbWVTdGFtcGluZ0NBLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAPa0e 277 | # H3aZW+M4hBJH2UOR9hHbm04IHdEoT8/T3HuBSyZeq3jSi5GXeWP7xCKhVireKCnC 278 | # s+8GZl2uVYFvQe+pPTScVJeCZSsMo1JCoZN2mMew/L4tpqVNbSpWO9QGFwfMEy60 279 | # HofN6V51sMLMXNTLfhVqs+e8haupWiArSozyAmGH/6oMQAh078qRh6wvJNU6gnh5 280 | # OruCP1QUAvVSu4kqVOcJVozZR5RRb/zPd++PGE3qF1P3xWvYViUJLsxtvge/mzA7 281 | # 5oBfFZSbdakHJe2BVDGIGVNVjOp8sNt70+kEoMF+T6tptMUNlehSR7vM+C13v9+9 282 | # ZOUKzfRUAYSyyEmYtsnpltD/GWX8eM70ls1V6QG/ZOB6b6Yum1HvIiulqJ1Elesj 283 | # 5TMHq8CWT/xrW7twipXTJ5/i5pkU5E16RSBAdOp12aw8IQhhA/vEbFkEiF2abhuF 284 | # ixUDobZaA0VhqAsMHOmaT3XThZDNi5U2zHKhUs5uHHdG6BoQau75KiNbh0c+hatS 285 | # F+02kULkftARjsyEpHKsF7u5zKRbt5oK5YGwFvgc4pEVUNytmB3BpIiowOIIuDgP 286 | # 5M9WArHYSAR16gc0dP2XdkMEP5eBsX7bf/MGN4K3HP50v/01ZHo/Z5lGLvNwQ7XH 287 | # Bx1yomzLP8lx4Q1zZKDyHcp4VQJLu2kWTsKsOqQxggWvMIIFqwIBATBqMFYxCzAJ 288 | # BgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAi 289 | # BgNVBAMTG0NlcnR1bSBDb2RlIFNpZ25pbmcgMjAyMSBDQQIQeAuTgzemd0ILREkK 290 | # U+Yq2jAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkq 291 | # hkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGC 292 | # NwIBFTAjBgkqhkiG9w0BCQQxFgQUTuLIOUX4XsjzDP2XZ7sLw1RlwZcwDQYJKoZI 293 | # hvcNAQEBBQAEggGAddY53CCLY3hamsX6Hzo4YPZlfipXZIQkGHm9j1/NsGo73kS6 294 | # gJqparhM1b8EuVeK3a3yd8msfy47s28MgePx1jbPwOCyqUuPEpbVCy1YiN2HDL5w 295 | # zkaOG+NqPq1U7x7weW1zjMzo7LgruNiJAdwuNKugOhtVvXvWaZI9fEWQ+J1O4gwg 296 | # Lm3RIboyYPNWH2VeyuDuLb0O9QzJOPQ/l7TkxCsWiiD6qXuTeXWmnjphrbqgGvSr 297 | # R1YMWetaB9AuQDUx+TBBhip5K0Tb+D0+SKZJiMXmSv2+tm8AbbKHVXBN9W+UmQbb 298 | # 865vak+xdafjwJrruW/n15MpSQaQGQkSkM/o6aT5vjjlc6IbFLEb1oMonrqmvGb4 299 | # wm2t/h+QT3gFcITxuuNQbfFps3vMFp3aZDIMJdx95u7ZxYbdEeZHhQ4R0RXJ72op 300 | # fisshDRkcQ2L/1a1zbsM48PfMJXc3T21NBPvPCPjiL/AZQ91b/Tb2MmFpX6oKt1U 301 | # LJYzL5LGFVsF5tL+oYIDIDCCAxwGCSqGSIb3DQEJBjGCAw0wggMJAgEBMHcwYzEL 302 | # MAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJE 303 | # aWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBD 304 | # QQIQC65mvFq6f5WHxvnpBOMzBDANBglghkgBZQMEAgEFAKBpMBgGCSqGSIb3DQEJ 305 | # AzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTI1MDMyNTIxMDYwN1owLwYJ 306 | # KoZIhvcNAQkEMSIEIICu/l67kWhL5JTKslB6g0IFCyfXScmuRynFThVx8hDpMA0G 307 | # CSqGSIb3DQEBAQUABIICAA03VFj78KasFhK3OTfOforsj0fM4e0wfPFkfq+UhJ9D 308 | # FfDjEUbQKJWEz6nSrNTAra3iDegXnW5RM5K+s5CD82POtvJiOQg+BckA7fni87yt 309 | # dunB8g3Se36uLbfjQ6+IOciRvheyDYOI2fk2vOs73YI14rrJqcO/e1J/+1ZmxaGc 310 | # GVRUSGOzHjoVzK6jod9DK3lGotfk33r4B+kvgJLizp+Wf0PcE6g/o5sH2htZszMt 311 | # QNGVGVdJUvG+j1dyIPG45I54Zs25V1x7Mb0z/Ai2nc1bLbKChHwHw0LU6lA1Hx5i 312 | # 2do7CBfqRJyB0eeja1IBKHpLHZZJ3GLAGnAHZXnQyOBrT2fDb5hXQK9XcuFvFDQc 313 | # tquAWEm/3sAj3eKrmEUu2fC5QPWdH6bmp1dj1jHmGTmH4Gm1RIt5zdVPfNL35I7W 314 | # yJdJea5kyJNBoeaDACi78ZAyAaWXVB06oHWKrdliiiPrOlzunJxEKey3u6O13ctS 315 | # G8bd5ylqFLCsi6PiRA71LTiNrQOeof40uB/v4SVnPvwd+vs22p74SF4812dZ89NU 316 | # RsZGU29zLGWeQSQhrpJJ/N3QAjSWhgIiE4Wuxge8AoBIYn0o+NyhSOES44maduNh 317 | # UyBl1nF/aN9FQ6F9A4NCEpeiclrCAoMAB0t0xODFRoJMYPAR2/u1hXftu5Ck+eHn 318 | # SIG # End signature block 319 | -------------------------------------------------------------------------------- /Public/Get-LatestOSBuild.ps1: -------------------------------------------------------------------------------- 1 | Function Get-LatestOSBuild { 2 | <# 3 | .SYNOPSIS 4 | Gets Windows patch release information (Version, Build, Availability date, Hotpatch, Preview, Out-of-band, Servicing option, KB article, KB URL and Catalog URL) for Windows client and server versions. 5 | Useful for scripting and automation purposes. Supports Windows 10 and Windows Server 2016 onwards. Supports Hotpatch on Windows 11 and Windows Server 2022. 6 | .DESCRIPTION 7 | Patch information retrieved from Microsoft Release Health / Update History pages and outputted in a usable format. 8 | These sources are updated regularly by Microsoft AFTER new patches are released. This means at times this info may not always be in sync with Windows Update. 9 | .PARAMETER OSName 10 | This parameter is optional. OS name you want to check. Default value is Win10. Accepted values: 11 | 12 | Windows Client OS Names - Win10, Win11, Win11Hotpatch. 13 | Windows Server OS Names - Server2016, Server2019, Server2022, Server2022Hotpatch, Server2025, Server Semi-annual = ServerSAC. 14 | .PARAMETER OSVersion 15 | This parameter is mandatory. OS version number you want to check. Accepted values: 16 | 17 | Windows Client OS Versions: 18 | CB/CBB/SAC (Semi-Annual Channel) - 1507, 1511, 1607, 1703, 1709, 1803, 1809, 1903, 1909, 2004, 20H2, 21H2, 22H2, 23H2, 24H2. 19 | Win 10 LTSB/LTSC (Long-Term Servicing Build/Channel) - 2015 = 1507, 2016 = 1607, 2019 = 1809, 2021 = 21H2. 20 | Win 11 LTSC (Long-Term Servicing Channel) - 2024 = 24H2. 21 | 22 | Window Server OS Versions: 23 | SAC (Semi-Annual Channel) - 1709, 1803, 1809, 1903, 1909, 2004, 20H2. 24 | LTSB/LTSC (Long-Term Servicing Build/Channel) - 2016 = 1607, 2019 = 1809, 2022 = 21H2, 2025 = 24H2. 25 | .PARAMETER LatestReleases 26 | This parameter is optional. Returns last x releases (where x is the number of releases you want to display). Default value is 1. 27 | .PARAMETER BuildOnly 28 | This parameter is optional. Returns full build number/s only. 29 | .PARAMETER ExcludePreview 30 | This parameter is optional. Excludes preview release/s. 31 | .PARAMETER ExcludeOutOfBand 32 | This parameter is optional. Excludes out-of-band release/s. 33 | .PARAMETER PreviewOnly 34 | This parameter is optional. Returns preview release/s only. 35 | .PARAMETER OutOfBandOnly 36 | This parameter is optional. Returns out-of-band/s only. 37 | .EXAMPLE 38 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 39 | Show all information on the latest available OS build for Windows 10 Version 22H2 in list format. 40 | .EXAMPLE 41 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -LatestReleases 2 42 | Show all information on the latest 2 releases of OS builds for Windows 10 Version 22H2 in list format. 43 | .EXAMPLE 44 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -ExcludePreview -LatestReleases 2 45 | Show all information on the latest 2 releases excluding preview of OS builds for Windows 10 Version 22H2 in list format. 46 | .EXAMPLE 47 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -ExcludeOutOfBand -LatestReleases 2 48 | Show all information on the latest 2 releases excluding out-of-band of OS builds for Windows 10 Version 22H2 in list format. 49 | .EXAMPLE 50 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -PreviewOnly -LatestReleases 2 51 | Show all information on the latest 2 preview releases of OS builds for Windows 10 Version 22H2 in list format. 52 | .EXAMPLE 53 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -OutOfBandOnly -LatestReleases 2 54 | Show all information on the latest 2 out-of-band releases of OS builds for Windows 10 Version 22H2 in list format. 55 | .EXAMPLE 56 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -BuildOnly 57 | Show only the latest available OS build for Windows 10 Version 22H2 in list format. 58 | .EXAMPLE 59 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -PreviewOnly -BuildOnly 60 | Show only the latest available preview OS build for Windows 10 Version 22H2 in list format. 61 | .EXAMPLE 62 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -OutOfBandOnly -BuildOnly 63 | Show only the latest available out-of-band OS build for for Windows 10 Version 22H2 in list format. 64 | .EXAMPLE 65 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 | ConvertTo-Json 66 | Show all information on the latest available OS build for Windows 10 Version 22H2 in json format. 67 | .EXAMPLE 68 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 | ConvertTo-Json | Out-File .\Get-LatestOSBuild.json 69 | Save the json format to a file on the latest available OS build for Windows 10 Version 22H2. 70 | 71 | .NOTES 72 | Forked from 'Get-Windows10ReleaseInformation.ps1' created by Fredrik Wall. 73 | https://github.com/FredrikWall/PowerShell/blob/master/Windows/Get-Windows10ReleaseInformation.ps1 74 | Uses code adapted from 'Get-CurrentPatchInfo.ps1' created by Trevor Jones. 75 | https://gist.githubusercontent.com/SMSAgentSoftware/79fb091a4b7806378fc0daa826dbfb47/raw/0f6b52cddf82b2aa836a813cf6bc910a52a48c9f/Get-CurrentPatchInfo.ps1 76 | #> 77 | 78 | Param( 79 | [CmdletBinding()] 80 | [Parameter(Mandatory = $true)] 81 | [String]$OSVersion, 82 | 83 | [Parameter(Mandatory = $false)] 84 | [String]$LatestReleases = 1, 85 | 86 | [Parameter(Mandatory = $false)] 87 | [ValidateSet('Win10','Win11','Win11Hotpatch','Server2016','Server2019','Server2022','Server2022Hotpatch','Server2025','Server2025Hotpatch','ServerSAC')] 88 | [String]$OSName = "Win10", 89 | 90 | [Parameter(Mandatory = $false)] 91 | [Switch]$BuildOnly, 92 | 93 | [Parameter(Mandatory = $false)] 94 | [Switch]$ExcludePreview, 95 | 96 | [Parameter(Mandatory = $false)] 97 | [Switch]$ExcludeOutOfBand, 98 | 99 | [Parameter(Mandatory = $false)] 100 | [Switch]$PreviewOnly, 101 | 102 | [Parameter(Mandatory = $false)] 103 | [Switch]$OutOfBandOnly 104 | ) 105 | 106 | # Disable progress bar to speed up Invoke-WebRequest calls 107 | $ProgressPreference = 'SilentlyContinue' 108 | 109 | # Enforce TLS 1.2 110 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 111 | 112 | # Define variables for OSName 113 | If (($OSName) -eq "Win11") { 114 | $OSBase = "Windows 11" 115 | $URL = "https://docs.microsoft.com/en-us/windows/release-health/windows11-release-information" 116 | $TableNumber = 1 117 | $AtomFeedUrl = "https://support.microsoft.com/en-us/feed/atom/4ec863cc-2ecd-e187-6cb3-b50c6545db92" 118 | } 119 | ElseIf (($OSName) -eq "Win10" -or ($OSName) -eq "Server2016" -or ($OSName) -eq "Server2019" -or ($OSName) -eq "ServerSAC") { 120 | $OSBase = "Windows 10" 121 | $URL = "https://docs.microsoft.com/en-us/windows/release-health/release-information" 122 | $TableNumber = 2 123 | $AtomFeedUrl = "https://support.microsoft.com/en-us/feed/atom/6ae59d69-36fc-8e4d-23dd-631d98bf74a9" 124 | } 125 | ElseIf ($OSName -eq "Win11HotPatch") { 126 | $URL = "https://support.microsoft.com/en-us/topic/release-notes-for-hotpatch-public-preview-on-windows-11-version-24h2-enterprise-clients-c117ee02-fd35-4612-8ea9-949c5d0ba6d1" 127 | $AtomFeedUrl = "https://support.microsoft.com/en-us/feed/atom/4ec863cc-2ecd-e187-6cb3-b50c6545db92" 128 | $CategoryName = "Windows 11, version 24H2 Enterprise clients" 129 | } 130 | ElseIf ($OSName -eq "Server2022" -or $OSName -eq "Server2022Hotpatch") { 131 | # Disabled automatic detection of hotfix as it is not a reliable method of guaranteeing devices are applying hotpatch updates, non-hotpatch updates can still be applied. 132 | # $HotpatchOS = Get-HotFix -Id KB5003508 -ErrorAction SilentlyContinue 133 | if ($OSName -eq "Server2022Hotpatch") { 134 | $URL = "https://support.microsoft.com/en-us/topic/release-notes-for-hotpatch-in-azure-automanage-for-windows-server-2022-4e234525-5bd5-4171-9886-b475dabe0ce8" 135 | $AtomFeedUrl = "https://support.microsoft.com/en-us/feed/atom/2d67e9fb-2bd2-6742-08ee-628da707657f" 136 | $CategoryName = "Release notes for Hotpatch in Azure Automanage for Windows Server 2022" 137 | } 138 | Else { 139 | $URL = "https://support.microsoft.com/en-us/topic/windows-server-2022-update-history-e1caa597-00c5-4ab9-9f3e-8212fe80b2ee" 140 | $CategoryName = "Windows Server 2022" 141 | } 142 | } 143 | ElseIf ($OSName -eq "Server2025" -or $OSName -eq "Server2025Hotpatch") { 144 | # Disabled automatic detection of hotfix as it is not a reliable method of guaranteeing devices are applying hotpatch updates, non-hotpatch updates can still be applied. 145 | # $HotpatchOS = Get-HotFix -Id KB5003508 -ErrorAction SilentlyContinue 146 | if ($OSName -eq "Server2025Hotpatch") { 147 | Throw "Get-LatestOSBuild: Windows Server 2025 Hotpatch is not yet supported" 148 | $URL = "https://support.microsoft.com/en-us/topic/release-notes-for-hotpatch-on-windows-server-2025-datacenter-azure-edition-c548437e-8c7a-4e27-99f4-e8746f97f8fa" 149 | $AtomFeedUrl = "N/A" 150 | $CategoryName = "Release notes for Hotpatch on Windows Server 2025 Datacenter Azure Edition" 151 | } 152 | Else { 153 | $URL = "https://support.microsoft.com/en-us/topic/windows-server-2025-update-history-10f58da7-e57b-4a9d-9c16-9f1dcd72d7d7" 154 | $CategoryName = "Windows Server 2025" 155 | } 156 | } 157 | Else { 158 | Throw "Get-LatestOSBuild: Unsupported Operating System" 159 | } 160 | 161 | # Enforce OSVersion for LTSC Server OSName to prevent incorrect OSVersion input 162 | If ($OSName -eq "Server2016") { 163 | $OSVersion = "1607" 164 | } 165 | ElseIf ($OSName -eq "Server2019") { 166 | $OSVersion = "1809" 167 | } 168 | ElseIf ($OSName -eq "Server2022" -or $OSName -eq "Server2022Hotpatch") { 169 | $OSVersion = "21H2" 170 | } 171 | ElseIf ($OSName -eq "Server2025" -or $OSName -eq "Server2025Hotpatch" -or $OSName -eq "Win11HotPatch") { 172 | $OSVersion = "24H2" 173 | } 174 | 175 | # Function used for to convert raw array from support URL to a parsed array (currently used only for Server 2022) 176 | Function Convert-ParsedArray { 177 | Param($Array) 178 | 179 | $ArrayList = New-Object System.Collections.ArrayList 180 | ForEach ($item in $Array) { 181 | $Match = [regex]::Match($item.Title, "Build (\d+\.\d+)") 182 | If ($Match.Success) { 183 | $OSBuild = [System.Version]::new($Match.Groups[1].Value) 184 | } 185 | Else { 186 | $OSBuild = $null 187 | } 188 | 189 | [Void]$ArrayList.Add([PSCustomObject]@{ 190 | Update = $item.Title.Replace('—', ' — ').Trim() 191 | KB = "KB" + $item.link.Split('/')[-1] 192 | InfoURL = "https://support.microsoft.com" + $item.Link 193 | OSBuild = $OSBuild # Add OSBuild here in the hashtable 194 | }) 195 | } 196 | Return $ArrayList 197 | } 198 | 199 | # Function used to get update release notes of specified OS as an array 200 | Function Get-ReleaseNotes { 201 | param ( 202 | [string]$webpage, 203 | [string]$CategoryName 204 | ) 205 | 206 | # Create an HtmlDocument object 207 | $htmlDocument = New-Object HtmlAgilityPack.HtmlDocument 208 | $htmlDocument.LoadHtml($webpage) 209 | 210 | # Check if HTML loaded correctly 211 | if ($htmlDocument.DocumentNode.InnerHtml -eq "") { 212 | return 213 | } 214 | 215 | # Find all categories with 'supLeftNavCategoryTitle' class 216 | $categoryTitles = $htmlDocument.DocumentNode.SelectNodes('//div[contains(@class, "supLeftNavCategoryTitle")]') 217 | 218 | if (!$categoryTitles) { 219 | return 220 | } 221 | 222 | # Initialize a list to store categorized links 223 | $categorizedLinks = @() 224 | 225 | # Loop through each category and extract article links 226 | foreach ($category in $categoryTitles) { 227 | $osName = $category.SelectSingleNode('.//a').InnerText 228 | 229 | # If CategoryName parameter is provided, only process matching categories 230 | if ($CategoryName -and $osName -notlike "*$CategoryName*") { 231 | continue 232 | } 233 | 234 | $articlesList = $category.ParentNode.SelectNodes('.//ul[contains(@class, "supLeftNavArticles")]') 235 | 236 | if ($articlesList) { 237 | foreach ($articleList in $articlesList) { 238 | foreach ($article in $articleList.SelectNodes('.//li')) { 239 | $articleLinkNode = $article.SelectSingleNode('.//a') 240 | if ($articleLinkNode) { 241 | $categorizedLinks += [PSCustomObject]@{ 242 | Category = $osName 243 | Link = $articleLinkNode.GetAttributeValue('href', '') 244 | Title = $articleLinkNode.InnerText.Trim() 245 | } 246 | } 247 | } 248 | } 249 | } 250 | } 251 | 252 | # Return the categorized links as output 253 | return $categorizedLinks | Where-Object { $_.Title -notlike "*$CategoryName*" } 254 | } 255 | 256 | # Obtain data from webpage 257 | Try { 258 | If ($OSName -eq "Server2022" -or $OSName -eq "Server2025") { 259 | $Webpage = Invoke-WebRequest -Uri $URL -UseBasicParsing -ErrorAction Stop 260 | } 261 | # Supports Server 2022 Hotpatch 262 | Else { 263 | If ($OSName -eq "Win11Hotpatch" -or $OSName -eq "Server2022Hotpatch" -or $OSName -eq "Server2025Hotpatch") { 264 | $Webpage = Invoke-WebRequest -Uri $URL -UseBasicParsing -ErrorAction Stop 265 | } 266 | Else { 267 | # All other OS 268 | $Webpage = Invoke-RestMethod -Uri $URL -UseBasicParsing -ErrorAction Stop 269 | } 270 | 271 | # Fetch the Atom feed content, used to obtain preview and out-of-band data 272 | If ($AtomFeedUrl -ne "N/A") { 273 | $response = Invoke-WebRequest -Uri $AtomFeedUrl -Method Get -UseBasicParsing -ErrorAction Stop 274 | 275 | # Extract raw content from the response 276 | $feedContent = $response.Content 277 | 278 | # Use regular expressions to extract entries 279 | $pattern = '\s*(.*?)<\/id>\s*(.*?)<\/title>\s*(.*?)<\/published>\s*(.*?)<\/updated>\s*\s*(.*?)<\/content>\s*<\/entry>' 280 | $AtomMatches = [regex]::Matches($feedContent, $pattern) 281 | 282 | If ($AtomMatches.Count -eq 0) { 283 | Throw "Get-LatestOSBuild: No elements found in the atom feed." 284 | } 285 | Else { 286 | # Initialize a list to store filtered feed entries 287 | $feedEntries = New-Object System.Collections.Generic.List[PSObject] 288 | 289 | # Iterate over matched entries 290 | ForEach ($AtomMatch in $AtomMatches) { 291 | $title = $AtomMatch.Groups[2].Value 292 | $link = $AtomMatch.Groups[5].Value 293 | 294 | # Filter out entries that do not contain "(OS Build" in the title 295 | If ($title -like '*(OS Build*') { 296 | # Create a hashtable for the entry 297 | $feedEntry = @{ 298 | Title = $title 299 | Link = $link 300 | } 301 | 302 | # Add the entry to the list 303 | $feedEntries.Add([PSCustomObject]$feedEntry) 304 | } 305 | } 306 | } 307 | } 308 | } 309 | } 310 | Catch { 311 | If ($_.Exception.Message -like '*403*') { 312 | Throw "Get-LatestOSBuild: Unable to obtain patch release information. Akamai CDN denial-of-service protection active. Error: $($_.Exception.Message)" 313 | } 314 | Else { 315 | Throw "Get-LatestOSBuild: Unable to obtain patch release information. Please check your internet connectivity. Error: $($_.Exception.Message)" 316 | } 317 | } 318 | 319 | # Server 2022 and 2025, Server 2022 Hotpatch, Server 2025 Hotpatch, Windows 11 Hotpatch. 320 | If ($OSName -eq "Win11Hotpatch" -or $OSName -eq "Server2022" -or $OSName -eq "Server2025" -or $OSName -eq "Server2022Hotpatch" -or $OSName -eq "Server2025Hotpatch") { 321 | $Table = @() 322 | $Table = @( 323 | $VersionDataRaw = $null 324 | $VersionDataRaw = Get-ReleaseNotes -Webpage $webpage -CategoryName $CategoryName | Sort-Object -Property Title -Unique 325 | $UniqueList = (Convert-ParsedArray -Array $VersionDataRaw) | Sort-Object OSBuild -Descending 326 | ForEach ($Update in $UniqueList) { 327 | $ResultObject = [Ordered] @{} 328 | # Support for Hotpatch 329 | If ($null -eq $Update.OSBuild.Major) { 330 | If ($OSName -eq "Win11Hotpatch") { 331 | $ResultObject["Version"] = "Version $OSVersion (OS build 26100)" 332 | } 333 | If ($OSName -eq "Server2022Hotpatch") { 334 | $ResultObject["Version"] = "Version $OSVersion (OS build 20348)" 335 | } 336 | If ($OSName -eq "Server2025Hotpatch") { 337 | $ResultObject["Version"] = "Version $OSVersion (OS build 26100)" 338 | } 339 | } 340 | Else { 341 | $ResultObject["Version"] = "Version $OSVersion (OS build $($Update.OSBuild.Major))" 342 | } 343 | # Support for Hotpatch - As we are performing matching based on date, this accounts for erroronus spaces in the date. 344 | If ($null -eq $Update.OSBuild) { 345 | $updateDate = ($Update.Update -replace '^([A-Za-z]+\s\d{1,2},\s\d{4}).*', '$1').Trim() 346 | $SourceOSBuild = $feedEntries.Title -like "*$updateDate*" 347 | $ResultObject["Build"] = [String]$SourceOSBuild -replace '.*OS Build (\d+\.\d+).*', '$1' 348 | } 349 | Else { 350 | $ResultObject["Build"] = [String]$Update.OSBuild 351 | } 352 | $GetDate = [regex]::Match($Update.Update,"(Jan(uary)?|Feb(ruary)?|Mar(ch)?|Apr(il)?|May|Jun(e)?|Jul(y)?|Aug(ust)?|Sep(tember)?|Oct(ober)?|Nov(ember)?|Dec(ember)?)\s+\d{1,2},\s+\d{4}").Value 353 | Try { 354 | $ConvertToDate = [Datetime]::ParseExact($GetDate, 'MMMM dd, yyyy', [Globalization.CultureInfo]::CreateSpecificCulture('en-US')) 355 | } 356 | Catch { 357 | $ConvertToDate = [Datetime]::ParseExact($GetDate, 'MMMM d, yyyy', [Globalization.CultureInfo]::CreateSpecificCulture('en-US')) 358 | } 359 | $FormatDate = Get-Date($ConvertToDate) -Format 'yyyy-MM-dd' 360 | $ResultObject["Availability date"] = $FormatDate 361 | If ($OSName -eq "Win11Hotpatch" -or $OSName -eq "Server2022Hotpatch" -or $OSName -eq "Server2025Hotpatch") { 362 | If ($Update.Update -match 'Baseline') { 363 | $ResultObject["Hotpatch"] = "False" 364 | } 365 | Else { 366 | $ResultObject["Hotpatch"] = "True" 367 | } 368 | } 369 | If ($Update.Update -match 'Preview') { 370 | $ResultObject["Preview"] = "True" 371 | } 372 | Else { 373 | $ResultObject["Preview"] = "False" 374 | } 375 | If ($Update.Update -match 'Out-of-band') { 376 | $ResultObject["Out-of-band"] = "True" 377 | } 378 | Else { 379 | $ResultObject["Out-of-band"] = "False" 380 | } 381 | $ResultObject["Servicing option"] = "LTSC" 382 | If (($OSName -eq "Win11Hotpatch" -or $OSName -eq "Server2022Hotpatch" -or $OSName -eq "Server2025Hotpatch") -and ($ResultObject.Hotpatch -eq "False")) { 383 | $ResultObject["KB source article"] = [regex]::Match($SourceOSBuild, 'KB\d{7}').Value 384 | $ResultObject["KB article"] = $Update.KB + " / " + $ResultObject.'KB source article' 385 | } 386 | Else { 387 | $ResultObject["KB article"] = $Update.KB 388 | } 389 | If (($OSName -eq "Win11Hotpatch" -or $OSName -eq "Server2022Hotpatch" -or $OSName -eq "Server2025Hotpatch") -and ($ResultObject.Hotpatch -eq "False")) { 390 | $ResultObject["KB URL"] = $Update.InfoURL 391 | $ResultObject["KB source URL"] = "https://support.microsoft.com/en-us/help" + $ResultObject.'KB source article' 392 | } 393 | Else { 394 | $ResultObject["KB URL"] = $Update.InfoURL 395 | } 396 | If (($OSName -eq "Win11Hotpatch" -or $OSName -eq "Server2022Hotpatch" -or $OSName -eq "Server2025Hotpatch") -and ($ResultObject.Hotpatch -eq "True")) { 397 | $ResultObject["Catalog URL"] = "N/A" 398 | } 399 | Else { 400 | $ResultObject["Catalog URL"] = "https://www.catalog.update.microsoft.com/Search.aspx?q=" + $Update.KB 401 | } 402 | # Cast hash table to a PSCustomObject 403 | If ($OSName -eq "Win11Hotpatch" -or $OSName -eq "Server2022Hotpatch" -or $OSName -eq "Server2025Hotpatch") { 404 | [PSCustomObject]$ResultObject | Select-Object -Property 'Version', 'Build', 'Availability date', 'Hotpatch', 'Preview', 'Out-of-band', 'Servicing option', 'KB article', 'KB URL', 'Catalog URL' 405 | } 406 | Else { 407 | [PSCustomObject]$ResultObject | Select-Object -Property 'Version', 'Build', 'Availability date', 'Preview', 'Out-of-band', 'Servicing option', 'KB article', 'KB URL', 'Catalog URL' 408 | } 409 | } 410 | ) 411 | 412 | # Include build information for Server 2022 RTM not included in Windows Update History 413 | $Server2022RTM = [PsCustomObject]@{ 414 | 'Version' = "Version 21H2 (OS build 20348)" 415 | 'Build' = "20348.169" 416 | 'Availability date' = "2021-08-18" 417 | 'Preview' = "False" 418 | 'Out-of-band' = "False" 419 | 'Servicing option' = "LTSC" 420 | 'KB article' = "N/A" 421 | 'KB URL' = "N/A" 422 | 'Catalog URL' = "N/A" 423 | } 424 | 425 | # Include build information for Server 2022 RTM not included in Windows Update History 426 | $Server2025RTM = [PsCustomObject]@{ 427 | 'Version' = "Version 24H2 (OS build 26100)" 428 | 'Build' = "26100.1742" 429 | 'Availability date' = "2024-09-10" 430 | 'Preview' = "False" 431 | 'Out-of-band' = "False" 432 | 'Servicing option' = "LTSC" 433 | 'KB article' = "N/A" 434 | 'KB URL' = "N/A" 435 | 'Catalog URL' = "N/A" 436 | } 437 | 438 | # Add / Sort Arrays 439 | If ($OSName -eq "Win11Hotpatch" -or $OSName -eq "Server2022Hotpatch" -or $OSName -eq "Server2025Hotpatch") { 440 | $Table = $Table | Sort-Object -Property 'Availability date' -Descending 441 | } 442 | ElseIf ($OSName -eq "Server2022") { 443 | $Table = $Table + $Server2022RTM | Sort-Object -Property 'Availability date' -Descending 444 | } 445 | ElseIf ($OSName -eq "Server2025") { 446 | $Table = $Table + $Server2025RTM | Sort-Object -Property 'Availability date' -Descending 447 | } 448 | 449 | } 450 | # All other OS 451 | Else { 452 | # Create HTML object using HTML Agility Pack 453 | $HTML = (New-Object HtmlAgilityPack.HtmlWeb).Load($URL) 454 | 455 | # Table Mapping - required to obtain preview and out-of-band information of versions 456 | $GetVersions = @($HTML.DocumentNode.SelectNodes("//strong")) 457 | $ReleaseVersions = ($GetVersions.innertext).Substring(0) 458 | $TableMapping = @() 459 | $TableMapping = ForEach ($Version in $ReleaseVersions) { 460 | # Windows 11 Base OS 461 | If ($OSBase -eq "Windows 11") { 462 | [PSCustomObject]@{ 463 | 'Base' = $OSBase 464 | 'Version' = $Version 465 | 'TableNumber'= $ReleaseVersions.IndexOf($Version) + 2 466 | } 467 | } 468 | # Windows 10 Base OS 469 | Else { 470 | [PSCustomObject]@{ 471 | 'Base' = $OSName 472 | 'Version' = $Version 473 | 'TableNumber'= $ReleaseVersions.IndexOf($Version) + 2 474 | } 475 | } 476 | } 477 | 478 | # Get version and table number to search of $OSVersion variable 479 | $SearchVersion = ($TableMapping | Where-Object { $_.Version -like "Version $OSVersion*(OS build*)" }).Version 480 | $SearchTable = ($TableMapping | Where-Object { $_.Version -like "Version $OSVersion*(OS build*)" }).TableNumber 481 | 482 | # Perform search and build table 483 | $Table = @() 484 | $Table = @( 485 | $Tables = @($HTML.DocumentNode.SelectNodes("//table")) 486 | Try { 487 | $Table = $Tables[$SearchTable] 488 | } 489 | Catch { 490 | Throw "Get-LatestOSBuild: Operating system name and version combination not supported. OS Name: $OSname, OS Version: $OSVersion, Error: $($_.Exception.Message)" 491 | } 492 | $Titles = @() 493 | $Rows = @($Table.Descendants("tr")) 494 | Foreach ($Row in $Rows) { 495 | # Remove not required row 496 | If ($Row.InnerText -like "*Servicing option*") { 497 | Continue 498 | } 499 | $Cells = @($Row.Descendants("td")) 500 | 501 | ## If we've found a table header, remember its titles 502 | If ($null -ne $Cells[0]) { 503 | $Titles = $Cells[0].ParentNode.ParentNode.SelectNodes(".//th").Innertext 504 | } 505 | 506 | ## If we haven't found any table headers, make up names "P1", "P2", etc. 507 | If (-not $Titles) { 508 | $Titles = @(1..($Cells.Count + 2) | ForEach-Object { "P$_" }) 509 | } 510 | 511 | ## Now go through the cells in the the row. For each, try to find the title that represents that column and create a hash table mapping those titles to content 512 | $ResultObject = [Ordered] @{} 513 | For ($Counter = 0; $Counter -lt $Cells.Count; $Counter++) { 514 | $ResultObject["Version"] = $SearchVersion 515 | } 516 | For ($Counter = 0; $Counter -lt $Cells.Count; $Counter++) { 517 | $Title = $Titles[$Counter] 518 | If (-not $Title) { 519 | Continue 520 | } 521 | If (![string]::IsNullOrEmpty($ResultObject.'Servicing option')) { 522 | # Resolve bullet encoding issue - Windows Terminal 523 | If ((Test-Path env:WT_SESSION) -eq "True") { 524 | # Directly replace the incorrect sequence with the correct bullet point 525 | $ResultObject['Servicing option'] = $ResultObject['Servicing option'].Replace([char]0xE2 + [char]0x80 + [char]0xA2, '•') 526 | } 527 | # Resolve bullet encoding issue - PowerShell 528 | Else { 529 | # Directly replace the incorrect sequence with the correct bullet point 530 | $ResultObject['Servicing option'] = $ResultObject.'Servicing option' -replace '\s*•\s*', ' • ' 531 | } 532 | } 533 | $ResultObject[$Title] = ("" + $Cells[$Counter].InnerText).Trim() 534 | If ((![string]::IsNullOrEmpty($ResultObject.'KB article')) -and ($ResultObject.'KB article' -ne "N/A")) { 535 | $KBURL = "https://support.microsoft.com/en-us/help/" + ($ResultObject."KB article").Trim("KB") 536 | $ResultObject["KB URL"] = $KBURL 537 | $ResultObject["Catalog URL"] = "https://www.catalog.update.microsoft.com/Search.aspx?q=" + $ResultObject.'KB article' 538 | If ($KBURL -ne " https://support.microsoft.com//en-us/help") { 539 | If ([string]::IsNullOrEmpty($feedEntries)) { 540 | $ResultObject["Preview"] = "Unknown" 541 | $ResultObject["Out-of-band"] = "Unknown" 542 | } 543 | 544 | $Item = $feedEntries | Where-Object -Property Title -match $ResultObject."KB article" 545 | If (($Item.Title -match ($ResultObject."KB article")) -and ($Item.Title -match 'Preview')) { 546 | $ResultObject["Preview"] = "True" 547 | } 548 | Else { 549 | $ResultObject["Preview"] = "False" 550 | } 551 | If (($Item.Title -match ($ResultObject."KB article")) -and ($Item.Title -match 'Out-of-band')) { 552 | $ResultObject["Out-of-band"] = "True" 553 | } 554 | Else { 555 | $ResultObject["Out-of-band"] = "False" 556 | } 557 | } 558 | } 559 | Else { 560 | $ResultObject["Preview"] = "False" 561 | $ResultObject["Out-of-band"] = "False" 562 | $ResultObject["KB article"] = "N/A" 563 | $ResultObject["KB URL"] = "N/A" 564 | $ResultObject["Catalog URL"] = "N/A" 565 | } 566 | } 567 | # Cast hash table to a PSCustomObject 568 | [PSCustomObject]$ResultObject | Select-Object -Property 'Version', 'Build', 'Availability date','Preview', 'Out-of-band', 'Servicing option', 'KB article', 'KB URL', 'Catalog URL' 569 | } 570 | ) 571 | } 572 | 573 | # Return filtered results based upon parameters 574 | If ($ExcludePreview -eq $true -and $ExcludeOutOfBand -eq $true -and $BuildOnly -eq $true) { 575 | # Excluding Preview and Out-of-band - Build 576 | ($Table | Where-Object { (($_.Preview -eq "False" -or $_.Preview -eq "Unknown") -and ($_.'Out-of-band' -eq "False" -or $_.'Out-of-band' -eq "Unknown")) } | Select-Object -First $LatestReleases)."Build" 577 | } 578 | ElseIf ($ExcludePreview -eq $true -and $ExcludeOutOfBand -eq $false -and $BuildOnly -eq $true) { 579 | # Excluding Preview - Build 580 | ($Table | Where-Object { $_.Preview -eq "False" -or $_.Preview -eq "Unknown" } | Select-Object -First $LatestReleases)."Build" 581 | } 582 | ElseIf ($ExcludePreview -eq $false -and $ExcludeOutOfBand -eq $true -and $BuildOnly -eq $true) { 583 | # Excluding Out-of-band - Build 584 | ($Table | Where-Object { $_.'Out-of-band' -eq "False" -or $_.'Out-of-band' -eq "Unknown" } | Select-Object -First $LatestReleases)."Build" 585 | } 586 | ElseIf ($ExcludePreview -eq $true -and $ExcludeOutOfBand -eq $true -and $BuildOnly -eq $false) { 587 | # Excluding Preview and Out-of-band 588 | ($Table | Where-Object { (($_.Preview -eq "False" -or $_.Preview -eq "Unknown") -and ($_.'Out-of-band' -eq "False" -or $_.'Out-of-band' -eq "Unknown")) } | Select-Object -First $LatestReleases) 589 | } 590 | ElseIf ($ExcludePreview -eq $true -and $ExcludeOutOfBand -eq $false -and $BuildOnly -eq $false) { 591 | # Excluding Preview 592 | ($Table | Where-Object { $_.Preview -eq "False" -or $_.Preview -eq "Unknown" } | Select-Object -First $LatestReleases) 593 | } 594 | ElseIf ($ExcludePreview -eq $false -and $ExcludeOutOfBand -eq $true -and $BuildOnly -eq $false) { 595 | # Excluding Out-of-band 596 | ($Table | Where-Object { $_.'Out-of-band' -eq "False" -or $_.'Out-of-band' -eq "Unknown" } | Select-Object -First $LatestReleases) 597 | } 598 | ElseIf ($PreviewOnly -eq $true -and $BuildOnly -eq $false) { 599 | # Preview Only 600 | ($Table | Where-Object { $_.Preview -eq "True" } | Select-Object -First $LatestReleases) 601 | } 602 | ElseIf ($PreviewOnly -eq $true -and $BuildOnly -eq $true) { 603 | # Preview Only - Build 604 | ($Table | Where-Object { $_.Preview -eq "True" } | Select-Object -First $LatestReleases)."Build" 605 | } 606 | ElseIf ($OutOfBandOnly -eq $true -and $BuildOnly -eq $false) { 607 | # Out-of-band Only 608 | ($Table | Where-Object { $_.'Out-of-band' -eq "True" } | Select-Object -First $LatestReleases) 609 | } 610 | ElseIf ($OutOfBandOnly -eq $true -and $BuildOnly -eq $true) { 611 | # Out-of-band Only - Build 612 | ($Table | Where-Object { $_.'Out-of-band' -eq "True" } | Select-Object -First $LatestReleases)."Build" 613 | } 614 | ElseIf ($BuildOnly -eq $true) { 615 | # Build 616 | ($Table | Select-Object -First $LatestReleases)."Build" 617 | } 618 | Else { 619 | # No parameters 620 | ($Table | Select-Object -First $LatestReleases) 621 | } 622 | } 623 | # SIG # Begin signature block 624 | # MIImbAYJKoZIhvcNAQcCoIImXTCCJlkCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB 625 | # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR 626 | # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUpGnqNmRqh4HJCifn6d37CgOl 627 | # 9a6ggiAnMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B 628 | # AQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD 629 | # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk 630 | # IElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQsw 631 | # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu 632 | # ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw 633 | # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz 634 | # 7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS 635 | # 5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7 636 | # bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfI 637 | # SKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jH 638 | # trHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14 639 | # Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2 640 | # h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt 641 | # 6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPR 642 | # iQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ER 643 | # ElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4K 644 | # Jpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAd 645 | # BgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SS 646 | # y4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAk 647 | # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAC 648 | # hjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS 649 | # b290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 650 | # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRV 651 | # HSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyh 652 | # hyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO 653 | # 0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo 654 | # 8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++h 655 | # UD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5x 656 | # aiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMIIGYzCCBEug 657 | # AwIBAgIQeAuTgzemd0ILREkKU+Yq2jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQG 658 | # EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMSQwIgYDVQQD 659 | # ExtDZXJ0dW0gQ29kZSBTaWduaW5nIDIwMjEgQ0EwHhcNMjQwNDExMDYwMzIxWhcN 660 | # MjUwNDExMDYwMzIwWjCBiDELMAkGA1UEBhMCR0IxDzANBgNVBAgMBkRvcnNldDEU 661 | # MBIGA1UEBwwLQk9VUk5FTU9VVEgxHjAcBgNVBAoMFU9wZW4gU291cmNlIERldmVs 662 | # b3BlcjEyMDAGA1UEAwwpT3BlbiBTb3VyY2UgRGV2ZWxvcGVyLCBBU0hMRVkgTUlD 663 | # SEFFTCBIT1cwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDpmsgFPzl4 664 | # 7W61kLLEp5ljxHC0ZZDti0+DL2JSAac1+bQW24vSjg4ABHhRB5CDKBuwVe2h0l+G 665 | # mEZHhKc9cz/RB+hUIJycd5Qx6VzsI1KJ0heEECm+oo3rywyqrd9RovkhkU2X29cR 666 | # UAa9SWZJJ2+/ImyzfyxzR+u0DD17BucHXWylQB2HGFCcX3kYUmgyZ/ANrgTvetW+ 667 | # n91OLxquC5+Nslh4MhbQAnItX79qrFLODd05S3SpQvdti16WGcRwXka4t5zdAMf6 668 | # v3c8ThHKPm/1TsyWsYAUMYJ9C0sNt+QYKNYHRX7DuA1OJBngAyGggtaXmqEpPBX2 669 | # SkDJ0uOeVDoJEOsxNydGZYPgvkIzsyF8YmEzkPK5x5elglYI0wfGwaMKshVbszj5 670 | # KXIPogeF/0vrEi8iIEd+Ro3ZY8ul+TliYf6P55tl3VCuKHDbzcYCtOXURmAPGwxC 671 | # 9wVvTr946eJr+emejOxg4/BZw5Q5GD6Qr8wwyodqholbzp8bfjTFmC8CAwEAAaOC 672 | # AXgwggF0MAwGA1UdEwEB/wQCMAAwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2Nj 673 | # c2NhMjAyMS5jcmwuY2VydHVtLnBsL2Njc2NhMjAyMS5jcmwwcwYIKwYBBQUHAQEE 674 | # ZzBlMCwGCCsGAQUFBzABhiBodHRwOi8vY2NzY2EyMDIxLm9jc3AtY2VydHVtLmNv 675 | # bTA1BggrBgEFBQcwAoYpaHR0cDovL3JlcG9zaXRvcnkuY2VydHVtLnBsL2Njc2Nh 676 | # MjAyMS5jZXIwHwYDVR0jBBgwFoAU3XRdTADbe5+gdMqxbvc8wDLAcM0wHQYDVR0O 677 | # BBYEFB7BnDzi+HIrft6IpueXUsx5LcgwMEsGA1UdIAREMEIwCAYGZ4EMAQQBMDYG 678 | # CyqEaAGG9ncCBQEEMCcwJQYIKwYBBQUHAgEWGWh0dHBzOi8vd3d3LmNlcnR1bS5w 679 | # bC9DUFMwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDgYDVR0PAQH/BAQDAgeAMA0GCSqG 680 | # SIb3DQEBCwUAA4ICAQBO5qPmZq+cztnjKtz9DyVBkZGaHj/TmfIZHrYfeQ0zdEVL 681 | # EszgokLuqNDdk0odEUHiockPB2dQn60oE3rNs+Wb1ZLLT18VoQTV0saMD3GiNzil 682 | # ejD4nIrhQ+vt0auxCvzBS8cQd24ePmjTqcIkL/u07xGhtT3LpUHUuHknUcEFjgs0 683 | # bUpGR5bofW8B9ZSC31g2i5PKZH8PUgOrTvg8oaMQYWyduKFnW8JRRGqypjUIFDE0 684 | # N224ox/U6GqqIl2cuC87H7WrHPEO6VjqSOx0PgybhSggGDKRNk9UQN1R45K/NCcw 685 | # 5+sIA1pjTZHnMhIJdxamhXiNq2S0U3LRVLSs1/BuXGENFWUraE4c51kDCiBPpGus 686 | # olI7/LLF3PIyYopyAWOGw0R7snlT+HJbfI7P6ObfYzzmIMdrKSaBkNtautcRYcIT 687 | # HAmbUAVplnpexQXXapSqxUfrPXWZk7xRLSXXqn915NbAoofVrTuLNXbv437KmoaN 688 | # p2J23oE7KzqdkoZ9SO4+8K+XKoEqBrPyxNB/i5UIId1Rsu5GE453usJf7zgsz4Ib 689 | # T8MQXjPq0WageEH3cL3qoPGBVbD++hLCJhqHPFJfM3zqxz4xZIRm7dY7GmcVc3Qq 690 | # H0biPnYkTfe8fwrT/IpEmVPdDnUSM92MhV25HV4CYU5LAISU1B070DMFAGc1uTCC 691 | # Bq4wggSWoAMCAQICEAc2N7ckVHzYR6z9KGYqXlswDQYJKoZIhvcNAQELBQAwYjEL 692 | # MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 693 | # LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0 694 | # MB4XDTIyMDMyMzAwMDAwMFoXDTM3MDMyMjIzNTk1OVowYzELMAkGA1UEBhMCVVMx 695 | # FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVz 696 | # dGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTCCAiIwDQYJKoZI 697 | # hvcNAQEBBQADggIPADCCAgoCggIBAMaGNQZJs8E9cklRVcclA8TykTepl1Gh1tKD 698 | # 0Z5Mom2gsMyD+Vr2EaFEFUJfpIjzaPp985yJC3+dH54PMx9QEwsmc5Zt+FeoAn39 699 | # Q7SE2hHxc7Gz7iuAhIoiGN/r2j3EF3+rGSs+QtxnjupRPfDWVtTnKC3r07G1decf 700 | # BmWNlCnT2exp39mQh0YAe9tEQYncfGpXevA3eZ9drMvohGS0UvJ2R/dhgxndX7RU 701 | # CyFobjchu0CsX7LeSn3O9TkSZ+8OpWNs5KbFHc02DVzV5huowWR0QKfAcsW6Th+x 702 | # tVhNef7Xj3OTrCw54qVI1vCwMROpVymWJy71h6aPTnYVVSZwmCZ/oBpHIEPjQ2OA 703 | # e3VuJyWQmDo4EbP29p7mO1vsgd4iFNmCKseSv6De4z6ic/rnH1pslPJSlRErWHRA 704 | # KKtzQ87fSqEcazjFKfPKqpZzQmiftkaznTqj1QPgv/CiPMpC3BhIfxQ0z9JMq++b 705 | # Pf4OuGQq+nUoJEHtQr8FnGZJUlD0UfM2SU2LINIsVzV5K6jzRWC8I41Y99xh3pP+ 706 | # OcD5sjClTNfpmEpYPtMDiP6zj9NeS3YSUZPJjAw7W4oiqMEmCPkUEBIDfV8ju2Tj 707 | # Y+Cm4T72wnSyPx4JduyrXUZ14mCjWAkBKAAOhFTuzuldyF4wEr1GnrXTdrnSDmuZ 708 | # DNIztM2xAgMBAAGjggFdMIIBWTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW 709 | # BBS6FtltTYUvcyl2mi91jGogj57IbzAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/ 710 | # 57qYrhwPTzAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwdwYI 711 | # KwYBBQUHAQEEazBpMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j 712 | # b20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdp 713 | # Q2VydFRydXN0ZWRSb290RzQuY3J0MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9j 714 | # cmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3JsMCAGA1Ud 715 | # IAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEA 716 | # fVmOwJO2b5ipRCIBfmbW2CFC4bAYLhBNE88wU86/GPvHUF3iSyn7cIoNqilp/GnB 717 | # zx0H6T5gyNgL5Vxb122H+oQgJTQxZ822EpZvxFBMYh0MCIKoFr2pVs8Vc40BIiXO 718 | # lWk/R3f7cnQU1/+rT4osequFzUNf7WC2qk+RZp4snuCKrOX9jLxkJodskr2dfNBw 719 | # CnzvqLx1T7pa96kQsl3p/yhUifDVinF2ZdrM8HKjI/rAJ4JErpknG6skHibBt94q 720 | # 6/aesXmZgaNWhqsKRcnfxI2g55j7+6adcq/Ex8HBanHZxhOACcS2n82HhyS7T6NJ 721 | # uXdmkfFynOlLAlKnN36TU6w7HQhJD5TNOXrd/yVjmScsPT9rp/Fmw0HNT7ZAmyEh 722 | # QNC3EyTN3B14OuSereU0cZLXJmvkOHOrpgFPvT87eK1MrfvElXvtCl8zOYdBeHo4 723 | # 6Zzh3SP9HSjTx/no8Zhf+yvYfvJGnXUsHicsJttvFXseGYs2uJPU5vIXmVnKcPA3 724 | # v5gA3yAWTyf7YGcWoWa63VXAOimGsJigK+2VQbc61RWYMbRiCQ8KvYHZE/6/pNHz 725 | # V9m8BPqC3jLfBInwAM1dwvnQI38AC+R2AibZ8GV2QqYphwlHK+Z/GqSFD/yYlvZV 726 | # VCsfgPrA8g4r5db7qS9EFUrnEw4d2zc4GqEr9u3WfPwwgga5MIIEoaADAgECAhEA 727 | # maOACiZVO2Wr3G6EprPqOTANBgkqhkiG9w0BAQwFADCBgDELMAkGA1UEBhMCUEwx 728 | # IjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNl 729 | # cnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRy 730 | # dXN0ZWQgTmV0d29yayBDQSAyMB4XDTIxMDUxOTA1MzIxOFoXDTM2MDUxODA1MzIx 731 | # OFowVjELMAkGA1UEBhMCUEwxITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMg 732 | # Uy5BLjEkMCIGA1UEAxMbQ2VydHVtIENvZGUgU2lnbmluZyAyMDIxIENBMIICIjAN 733 | # BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnSPPBDAjO8FGLOczcz5jXXp1ur5c 734 | # Tbq96y34vuTmflN4mSAfgLKTvggv24/rWiVGzGxT9YEASVMw1Aj8ewTS4IndU8s7 735 | # VS5+djSoMcbvIKck6+hI1shsylP4JyLvmxwLHtSworV9wmjhNd627h27a8RdrT1P 736 | # H9ud0IF+njvMk2xqbNTIPsnWtw3E7DmDoUmDQiYi/ucJ42fcHqBkbbxYDB7SYOou 737 | # u9Tj1yHIohzuC8KNqfcYf7Z4/iZgkBJ+UFNDcc6zokZ2uJIxWgPWXMEmhu1gMXgv 738 | # 8aGUsRdaCtVD2bSlbfsq7BiqljjaCun+RJgTgFRCtsuAEw0pG9+FA+yQN9n/kZtM 739 | # LK+Wo837Q4QOZgYqVWQ4x6cM7/G0yswg1ElLlJj6NYKLw9EcBXE7TF3HybZtYvj9 740 | # lDV2nT8mFSkcSkAExzd4prHwYjUXTeZIlVXqj+eaYqoMTpMrfh5MCAOIG5knN4Q/ 741 | # JHuurfTI5XDYO962WZayx7ACFf5ydJpoEowSP07YaBiQ8nXpDkNrUA9g7qf/rCkK 742 | # bWpQ5boufUnq1UiYPIAHlezf4muJqxqIns/kqld6JVX8cixbd6PzkDpwZo4SlADa 743 | # Ci2JSplKShBSND36E/ENVv8urPS0yOnpG4tIoBGxVCARPCg1BnyMJ4rBJAcOSnAW 744 | # d18Jx5n858JSqPECAwEAAaOCAVUwggFRMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O 745 | # BBYEFN10XUwA23ufoHTKsW73PMAywHDNMB8GA1UdIwQYMBaAFLahVDkCw6A/joq8 746 | # +tT4HKbROg79MA4GA1UdDwEB/wQEAwIBBjATBgNVHSUEDDAKBggrBgEFBQcDAzAw 747 | # BgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vY3JsLmNlcnR1bS5wbC9jdG5jYTIuY3Js 748 | # MGwGCCsGAQUFBwEBBGAwXjAoBggrBgEFBQcwAYYcaHR0cDovL3N1YmNhLm9jc3At 749 | # Y2VydHVtLmNvbTAyBggrBgEFBQcwAoYmaHR0cDovL3JlcG9zaXRvcnkuY2VydHVt 750 | # LnBsL2N0bmNhMi5jZXIwOQYDVR0gBDIwMDAuBgRVHSAAMCYwJAYIKwYBBQUHAgEW 751 | # GGh0dHA6Ly93d3cuY2VydHVtLnBsL0NQUzANBgkqhkiG9w0BAQwFAAOCAgEAdYhY 752 | # D+WPUCiaU58Q7EP89DttyZqGYn2XRDhJkL6P+/T0IPZyxfxiXumYlARMgwRzLRUS 753 | # tJl490L94C9LGF3vjzzH8Jq3iR74BRlkO18J3zIdmCKQa5LyZ48IfICJTZVJeChD 754 | # UyuQy6rGDxLUUAsO0eqeLNhLVsgw6/zOfImNlARKn1FP7o0fTbj8ipNGxHBIutiR 755 | # sWrhWM2f8pXdd3x2mbJCKKtl2s42g9KUJHEIiLni9ByoqIUul4GblLQigO0ugh7b 756 | # WRLDm0CdY9rNLqyA3ahe8WlxVWkxyrQLjH8ItI17RdySaYayX3PhRSC4Am1/7mAT 757 | # wZWwSD+B7eMcZNhpn8zJ+6MTyE6YoEBSRVrs0zFFIHUR08Wk0ikSf+lIe5Iv6RY3 758 | # /bFAEloMU+vUBfSouCReZwSLo8WdrDlPXtR0gicDnytO7eZ5827NS2x7gCBibESY 759 | # kOh1/w1tVxTpV2Na3PR7nxYVlPu1JPoRZCbH86gc96UTvuWiOruWmyOEMLOGGniR 760 | # +x+zPF/2DaGgK2W1eEJfo2qyrBNPvF7wuAyQfiFXLwvWHamoYtPZo0LHuH8X3n9C 761 | # +xN4YaNjt2ywzOr+tKyEVAotnyU9vyEVOaIYMk3IeBrmFnn0gbKeTTyYeEEUz/Qw 762 | # t4HOUBCrW602NCmvO1nm+/80nLy5r0AZvCQxaQ4wgga8MIIEpKADAgECAhALrma8 763 | # Wrp/lYfG+ekE4zMEMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcwFQYD 764 | # VQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBH 765 | # NCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMjQwOTI2MDAwMDAw 766 | # WhcNMzUxMTI1MjM1OTU5WjBCMQswCQYDVQQGEwJVUzERMA8GA1UEChMIRGlnaUNl 767 | # cnQxIDAeBgNVBAMTF0RpZ2lDZXJ0IFRpbWVzdGFtcCAyMDI0MIICIjANBgkqhkiG 768 | # 9w0BAQEFAAOCAg8AMIICCgKCAgEAvmpzn/aVIauWMLpbbeZZo7Xo/ZEfGMSIO2qZ 769 | # 46XB/QowIEMSvgjEdEZ3v4vrrTHleW1JWGErrjOL0J4L0HqVR1czSzvUQ5xF7z4I 770 | # Qmn7dHY7yijvoQ7ujm0u6yXF2v1CrzZopykD07/9fpAT4BxpT9vJoJqAsP8YuhRv 771 | # flJ9YeHjes4fduksTHulntq9WelRWY++TFPxzZrbILRYynyEy7rS1lHQKFpXvo2G 772 | # ePfsMRhNf1F41nyEg5h7iOXv+vjX0K8RhUisfqw3TTLHj1uhS66YX2LZPxS4oaf3 773 | # 3rp9HlfqSBePejlYeEdU740GKQM7SaVSH3TbBL8R6HwX9QVpGnXPlKdE4fBIn5BB 774 | # FnV+KwPxRNUNK6lYk2y1WSKour4hJN0SMkoaNV8hyyADiX1xuTxKaXN12HgR+8Wu 775 | # lU2d6zhzXomJ2PleI9V2yfmfXSPGYanGgxzqI+ShoOGLomMd3mJt92nm7Mheng/T 776 | # BeSA2z4I78JpwGpTRHiT7yHqBiV2ngUIyCtd0pZ8zg3S7bk4QC4RrcnKJ3FbjyPA 777 | # GogmoiZ33c1HG93Vp6lJ415ERcC7bFQMRbxqrMVANiav1k425zYyFMyLNyE1QulQ 778 | # SgDpW9rtvVcIH7WvG9sqYup9j8z9J1XqbBZPJ5XLln8mS8wWmdDLnBHXgYly/p1D 779 | # hoQo5fkCAwEAAaOCAYswggGHMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAA 780 | # MBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsG 781 | # CWCGSAGG/WwHATAfBgNVHSMEGDAWgBS6FtltTYUvcyl2mi91jGogj57IbzAdBgNV 782 | # HQ4EFgQUn1csA3cOKBWQZqVjXu5Pkh92oFswWgYDVR0fBFMwUTBPoE2gS4ZJaHR0 783 | # cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5NlNI 784 | # QTI1NlRpbWVTdGFtcGluZ0NBLmNybDCBkAYIKwYBBQUHAQEEgYMwgYAwJAYIKwYB 785 | # BQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBYBggrBgEFBQcwAoZMaHR0 786 | # cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5 787 | # NlNIQTI1NlRpbWVTdGFtcGluZ0NBLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAPa0e 788 | # H3aZW+M4hBJH2UOR9hHbm04IHdEoT8/T3HuBSyZeq3jSi5GXeWP7xCKhVireKCnC 789 | # s+8GZl2uVYFvQe+pPTScVJeCZSsMo1JCoZN2mMew/L4tpqVNbSpWO9QGFwfMEy60 790 | # HofN6V51sMLMXNTLfhVqs+e8haupWiArSozyAmGH/6oMQAh078qRh6wvJNU6gnh5 791 | # OruCP1QUAvVSu4kqVOcJVozZR5RRb/zPd++PGE3qF1P3xWvYViUJLsxtvge/mzA7 792 | # 5oBfFZSbdakHJe2BVDGIGVNVjOp8sNt70+kEoMF+T6tptMUNlehSR7vM+C13v9+9 793 | # ZOUKzfRUAYSyyEmYtsnpltD/GWX8eM70ls1V6QG/ZOB6b6Yum1HvIiulqJ1Elesj 794 | # 5TMHq8CWT/xrW7twipXTJ5/i5pkU5E16RSBAdOp12aw8IQhhA/vEbFkEiF2abhuF 795 | # ixUDobZaA0VhqAsMHOmaT3XThZDNi5U2zHKhUs5uHHdG6BoQau75KiNbh0c+hatS 796 | # F+02kULkftARjsyEpHKsF7u5zKRbt5oK5YGwFvgc4pEVUNytmB3BpIiowOIIuDgP 797 | # 5M9WArHYSAR16gc0dP2XdkMEP5eBsX7bf/MGN4K3HP50v/01ZHo/Z5lGLvNwQ7XH 798 | # Bx1yomzLP8lx4Q1zZKDyHcp4VQJLu2kWTsKsOqQxggWvMIIFqwIBATBqMFYxCzAJ 799 | # BgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAi 800 | # BgNVBAMTG0NlcnR1bSBDb2RlIFNpZ25pbmcgMjAyMSBDQQIQeAuTgzemd0ILREkK 801 | # U+Yq2jAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkq 802 | # hkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGC 803 | # NwIBFTAjBgkqhkiG9w0BCQQxFgQU7xAtUUh2O0osswOit4GCPcNjlkkwDQYJKoZI 804 | # hvcNAQEBBQAEggGAz38zCeIjYTLk+rgwK8a0E1qg3rcX3cubSKoHvtP2MSXi24iv 805 | # 1b1YY3AfdSoD0+066PWe+yMtqC79pNdaRlFPlitvhzIQfNtnoDJL79Q2bCJuOVzf 806 | # KI8j+KN4FzU4qokDAb8sgu6nB+8k9Iz0AHPeZfS8hV17ufp0vWO6Gigfz0qTMpye 807 | # O4sqBcUfTBeT9obLDDsXnF0Cj8Kt3c15rLGQbbo8cR1G+6Cf3La7Bxjg9COqPY40 808 | # RVMbIroDQeOUDk2OqM+XEUieK8iYwDDxuXiTEsk8ZT4n9xtd4Hnucm7t9M2grAah 809 | # 3L7CX0ON3f00lKlRbVu95NOPa6AUcFgof2hTxZ9rfaAUwKYcWJvIPNcF0Y4sYZTK 810 | # KlS8f4LfIKoEn9FUnC330OFMbPuAqNwxFnAdAtF8IY3XzWp/GuGg21+vIPM8wbsE 811 | # 7/i08p2QTVES/GYb6Z3sfKFRnLq32OOwqdbH382Z7eDiNKqj3f+hWzf17/Yfp+dV 812 | # L59ma5a3K+gk2lAEoYIDIDCCAxwGCSqGSIb3DQEJBjGCAw0wggMJAgEBMHcwYzEL 813 | # MAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJE 814 | # aWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBD 815 | # QQIQC65mvFq6f5WHxvnpBOMzBDANBglghkgBZQMEAgEFAKBpMBgGCSqGSIb3DQEJ 816 | # AzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTI1MDMyMjE1MDQ1N1owLwYJ 817 | # KoZIhvcNAQkEMSIEIN3OYd2GH+e5UM/e+HQ6RKQ0SGhSFnSkQAe2IVm9q9eNMA0G 818 | # CSqGSIb3DQEBAQUABIICAIlf6hxvw/79+MpmWyFdSb7euqcbEWCOkYaDPq84oXHc 819 | # JUXAejbOfOnlEA5SxqwgSMGEapPlEaGLcFzK6T0ftG+WqwGkx8PL4vMUEw2yOVkD 820 | # +zdZzOzQAg2kU24SzwmwWs245aMGqeE2NmPfA0inPnwUWwGFJALiwltV7OrD+huN 821 | # yIf8Qv2DjYE+e2RGdyVJsrAkurdG87388GfYsX692lOXoehjH1IdtDXrAbaZfeVL 822 | # F3NUDqL678NwT9Ni6t8rQ8ADyrhPb/t4R6nI51N2WZR+UGjihTyvRtBbYTfK7Y03 823 | # /vW3l3kLqAxiCqtrcoEbjMa2FgxkgwAZ1qETbof2IbI4CDJKM+veKgJV3pDLiEXA 824 | # ufeRrijtx+OpJ18FvNIZ0z0Az4DvCU5NUXInV85sKP+RfmzGkEVrlxTmiCyQNnwM 825 | # HbmzO1MKfYZiHINoJUXFGMFHZcCoWXZculPO6toQL8PA49x91UxGy/y2agMRrZXV 826 | # OLFXzbmXPukLj9ZjA7PB1d6UTuVZ7ggfVRZFb1CsnJrdqToFLYgCtB9i15GUeNpD 827 | # Ur6IdpG0tCfSkkLpa2bZPu5qIKrnP+MyexLDqPv/CBbXXf+HJOkU71/A8LrCDcQ8 828 | # qYYMiScnuNdpswdTwGhfyRe5D2K/BC+HWW8TrCPDA0hr8tQgjuRqzaoVtLn1aJ/n 829 | # SIG # End signature block 830 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WindowsOSBuild 2 | [![License][license-badge]][license] 3 | [![PowerShell Gallery][psgallery-badge]][psgallery] 4 | [![PowerShell Gallery Version][psgallery-version-badge]][psgallery] 5 | [![Codacy Badge](https://app.codacy.com/project/badge/Grade/ec81538145f64de7ad264606ed790407)](https://www.codacy.com/gh/AshleyHow/WindowsOSBuild/dashboard?utm_source=github.com&utm_medium=referral&utm_content=AshleyHow/WindowsOSBuild&utm_campaign=Badge_Grade) 6 | [![Build status](https://ci.appveyor.com/api/projects/status/o8l8510lkoo7igy1?svg=true)](https://ci.appveyor.com/project/ah-uk/windowsosbuild) 7 | 8 | ![alt text](https://github.com/AshleyHow/WindowsOSBuild/blob/main/WindowsOSBuild.png) 9 | 10 | Gets Windows patch release information (Version, Build, Availability date, Hotpatch, Preview, Out-of-band, Servicing option, KB article, KB URL and Catalog URL) for Windows client and server versions. Useful for scripting and automation purposes. Supports Windows 10 and Windows Server 2016 onwards. Supports Hotpatch on Windows 11 and Windows Server 2022. 11 | 12 | Patch information retrieved from Microsoft Release Health / Update History and relevant Atom feed pages (Preview, Out-of-Band and Hotpatch info) outputted in a usable format. These sources are updated regularly by Microsoft AFTER new patches are released. This means at times this info may not always be in sync with Windows Update. 13 | 14 | The project is now fully signed using a code singing certificate. If you have found this project useful please [:heart:Sponsor](https://github.com/sponsors/AshleyHow) to help fund future code signing certificates. 15 | 16 | ## Installing the Module 17 | 18 | ### PowerShell Support 19 | 20 | WindowsOSBuild supports Windows PowerShell 5.0, 5.1 and 7.0+. 21 | 22 | ### Install from the PowerShell Gallery 23 | 24 | The WindowsOSBuild module is published to the PowerShell Gallery and can be found here: [WindowsOSBuild](https://www.powershellgallery.com/packages/WindowsOSBuild/). This is the best and recommend method to install WindowsOSBuild. 25 | 26 | The module can be installed from the gallery with: 27 | 28 | ```powershell 29 | Install-Module -Name WindowsOSBuild 30 | ``` 31 | 32 | ### Updating the Module 33 | 34 | If you have installed a previous version of the module from the gallery, you can install the latest update with `Update-Module` and the `-Force` parameter: 35 | 36 | ```powershell 37 | Update-Module -Name WindowsOSBuild -Force 38 | ``` 39 | 40 | ## Get-LatestOSBuild Function 41 | 42 | Gets windows patch release information (Build, KB Number, Release Date etc) for Windows client and server versions. Useful for scripting and automation purposes. Supports Windows 10 and Windows Server 2016 onwards. Supports Hotpatch on Windows 11 and Windows Server 2022. 43 | 44 | ### Parameters 45 | 46 | - OSName 47 | 48 | This parameter is optional. OS name you want to check. Default value is Win10. Supported accepted values: 49 | 50 | | OS Name | Version | 51 | | :---------------------------------------------------| :-----------------------------------------------------------------------------------------------------------------------| 52 | | Windows Client OS Names | Win10, Win11, Win11Hotpatch. | 53 | | Windows Server OS Names | Server2016, Server2019, Server2022, Server2022Hotpatch, Server2025, Server Semi-annual = ServerSAC. | 54 | 55 | - OSVersion 56 | 57 | This parameter is mandatory. OS version number you want to check. Supported accepted values: 58 | 59 | | Windows Client OS | Version | 60 | | :-------------------------------------------------- | :-----------------------------------------------------------------------------------------------------------------------| 61 | | CB/CBB/SAC (Semi-Annual Channel) | 1507, 1511, 1607, 1703, 1709, 1803, 1809, 1903, 1909, 2004, 20H2, 21H1, 21H2, 22H2, 23H2, 24H2. | 62 | | Win 10 LTSB/LTSC (Long-Term Servicing Build/Channel)| 2015 = 1507, 2016 = 1607, 2019 = 1809, 2021 = 21H2. | 63 | | Win 11 LTSC (Long-Term Servicing Channel) | 2024 = 24H2. | 64 | 65 | | Windows Server OS | Version | 66 | | :-------------------------------------------------- | :-----------------------------------------------------------------------------------------------------------------------| 67 | | SAC (Semi-Annual Channel) | 1709, 1803, 1809, 1903, 1909, 2004, 20H2. | 68 | | LTSB/LTSC (Long-Term Servicing Build/Channel) | 2016 = 1607, 2019 = 1809, 2022 = 21H2, 2025 = 24H2. | 69 | 70 | - LatestReleases 71 | 72 | This parameter is optional. Returns last x releases (where x is the number of releases you want to display). Default value is 1. 73 | 74 | - BuildOnly 75 | 76 | This parameter is optional. Returns only the full build number/s of the OS Version. 77 | 78 | - ExcludePreview 79 | 80 | This parameter is optional. Excludes preview releases. 81 | 82 | - ExcludeOutOfBand 83 | 84 | This parameter is optional. Excludes out-of-band releases. 85 | 86 | - PreviewOnly 87 | 88 | This parameter is optional. Returns preview release/s only. 89 | 90 | - OutOfBandOnly 91 | 92 | This parameter is optional. Returns out-of-band/s only. 93 | 94 | ## Get-CurrentOSBuild Function 95 | 96 | Gets the currently installed OS Build release information. Supports Windows 10 and Windows Server 2016 onwards. Supports Hotpatch on Windows Server 2022 Azure Edition. 97 | 98 | Installed OS Build number or detailed information (Version, Build, Availability date, Hotpatch, Preview, Out-of-band, Servicing option, KB article, KB URL and Catalog URL). 99 | 100 | ### Parameters 101 | 102 | - Detailed 103 | 104 | This parameter is optional. Returns detailed information about the installed OS Build. 105 | 106 | ## Usage 107 | 108 | ### Get-CurrentOSBuild 109 | 110 | Show only the build number for the installed OS Build. 111 | ```powershell 112 | Get-CurrentOSBuild 113 | ``` 114 | Show detailed information for the installed OS Build. 115 | ```powershell 116 | Get-CurrentOSBuild -Detailed 117 | ``` 118 | ### Get-LatestOSBuild 119 | 120 | Show all information on the latest available OS build for Windows 10 Version 22H2 in list format. 121 | ```powershell 122 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 123 | ``` 124 | Show all information on the latest 2 releases of OS builds for Windows 10 Version 22H2 in list format. 125 | ```powershell 126 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -LatestReleases 2 127 | ``` 128 | Show all information on the latest 2 releases excluding preview of OS builds for Windows 10 Version 22H2 in list format. 129 | ```powershell 130 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -ExcludePreview -LatestReleases 2 131 | ``` 132 | Show all information on the latest 2 releases excluding out-of-band of OS builds for Windows 10 Version 22H2 in list format. 133 | ```powershell 134 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -ExcludeOutOfBand -LatestReleases 2 135 | ``` 136 | Show all information on the latest 2 preview releases of OS builds for Windows 10 Version 22H2 in list format. 137 | ```powershell 138 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -PreviewOnly -LatestReleases 2 139 | ``` 140 | Show all information on the latest 2 out-of-band releases of OS builds for Windows 10 Version 22H2 in list format. 141 | ```powershell 142 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -OutOfBandOnly -LatestReleases 2 143 | ``` 144 | Show only the latest available OS build for Windows 10 Version 22H2 in list format. 145 | ```powershell 146 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -BuildOnly 147 | ``` 148 | Show only the latest available preview OS build for Windows 10 Version 22H2 in list format. 149 | ```powershell 150 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -PreviewOnly -BuildOnly 151 | ``` 152 | Show only the latest available out-of-band OS build for for Windows 10 Version 22H2 in list format. 153 | ```powershell 154 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -OutOfBandOnly -BuildOnly 155 | ``` 156 | Show all information on the latest available OS build for Windows 10 Version 22H2 in json format. 157 | ```powershell 158 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 | ConvertTo-Json 159 | ``` 160 | Save the json format to a file on the latest available OS build for Windows 10 Version 22H2. 161 | ```powershell 162 | Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 | ConvertTo-Json | Out-File .\Get-LatestOSBuild.json 163 | ``` 164 | 165 | ## Output 166 | 167 | ### Get-CurrentOSBuild 168 | 169 | ```powershell 170 | PS C:\Users\Ashley> Get-CurrentOSBuild 171 | 172 | 19045.3324 173 | ``` 174 | 175 | ```powershell 176 | PS C:\Users\Ashley> Get-CurrentOSBuild -Detailed 177 | 178 | Version : Version 22H2 (OS build 19045) 179 | Build : 19045.3324 180 | Availability date : 2023-08-08 181 | Preview : False 182 | Out-of-band : False 183 | Servicing option : General Availability Channel 184 | KB article : KB5029244 185 | KB URL : https://support.microsoft.com/help/5029244 186 | Catalog URL : https://www.catalog.update.microsoft.com/Search.aspx?q=KB5029244 187 | ``` 188 | ### Get-LatestOSBuild 189 | 190 | ```powershell 191 | PS C:\Users\Ashley> Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -LatestReleases 2 -BuildOnly 192 | 193 | 19045.3393 194 | 19045.3324 195 | ``` 196 | 197 | ```powershell 198 | PS C:\Users\Ashley> Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -LatestReleases 2 199 | 200 | Version : Version 22H2 (OS build 19045) 201 | Build : 19045.3393 202 | Availability date : 2023-08-22 203 | Preview : True 204 | Out-of-band : False 205 | Servicing option : General Availability Channel 206 | KB article : KB5029331 207 | KB URL : https://support.microsoft.com/help/5029331 208 | Catalog URL : https://www.catalog.update.microsoft.com/Search.aspx?q=KB5029331 209 | 210 | Version : Version 22H2 (OS build 19045) 211 | Build : 19045.3324 212 | Availability date : 2023-08-08 213 | Preview : False 214 | Out-of-band : False 215 | Servicing option : General Availability Channel 216 | KB article : KB5029244 217 | KB URL : https://support.microsoft.com/help/5029244 218 | Catalog URL : https://www.catalog.update.microsoft.com/Search.aspx?q=KB5029244 219 | ``` 220 | 221 | ```powershell 222 | PS C:\Users\Ashley> Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -LatestReleases 20 | Format-Table 223 | 224 | Version Build Availability date Preview Out-of-band Servicing option KB article KB URL Catalog URL 225 | ------- ----- ----------------- ------- ----------- ---------------- ---------- ------ ----------- 226 | Version 21H2 (OS build 19044) 19044.3324 2023-08-08 False False LTSC • General Availability Channel KB5029244 https://support.microsoft.com/help/5029244 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5029244 227 | Version 21H2 (OS build 19044) 19044.3208 2023-07-11 False False LTSC • General Availability Channel KB5028166 https://support.microsoft.com/help/5028166 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5028166 228 | Version 21H2 (OS build 19044) 19044.3086 2023-06-13 False False LTSC • General Availability Channel KB5027215 https://support.microsoft.com/help/5027215 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5027215 229 | Version 21H2 (OS build 19044) 19044.2965 2023-05-09 False False LTSC • General Availability Channel KB5026361 https://support.microsoft.com/help/5026361 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5026361 230 | Version 21H2 (OS build 19044) 19044.2846 2023-04-11 False False LTSC • General Availability Channel KB5025221 https://support.microsoft.com/help/5025221 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5025221 231 | Version 21H2 (OS build 19044) 19044.2788 2023-03-21 True False LTSC • General Availability Channel KB5023773 https://support.microsoft.com/help/5023773 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5023773 232 | Version 21H2 (OS build 19044) 19044.2728 2023-03-14 False False LTSC • General Availability Channel KB5023696 https://support.microsoft.com/help/5023696 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5023696 233 | Version 21H2 (OS build 19044) 19044.2673 2023-02-21 True False LTSC • General Availability Channel KB5022906 https://support.microsoft.com/help/5022906 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5022906 234 | Version 21H2 (OS build 19044) 19044.2604 2023-02-14 False False LTSC • General Availability Channel KB5022834 https://support.microsoft.com/help/5022834 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5022834 235 | Version 21H2 (OS build 19044) 19044.2546 2023-01-19 True False LTSC • General Availability Channel KB5019275 https://support.microsoft.com/help/5019275 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5019275 236 | Version 21H2 (OS build 19044) 19044.2486 2023-01-10 False False LTSC • General Availability Channel KB5022282 https://support.microsoft.com/help/5022282 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5022282 237 | Version 21H2 (OS build 19044) 19044.2364 2022-12-13 False False LTSC • General Availability Channel KB5021233 https://support.microsoft.com/help/5021233 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5021233 238 | Version 21H2 (OS build 19044) 19044.2311 2022-11-15 True False LTSC • General Availability Channel KB5020030 https://support.microsoft.com/help/5020030 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5020030 239 | Version 21H2 (OS build 19044) 19044.2251 2022-11-08 False False LTSC • General Availability Channel KB5019959 https://support.microsoft.com/help/5019959 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5019959 240 | Version 21H2 (OS build 19044) 19044.2194 2022-10-28 False True LTSC • General Availability Channel KB5020953 https://support.microsoft.com/help/5020953 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5020953 241 | Version 21H2 (OS build 19044) 19044.2193 2022-10-25 True False LTSC • General Availability Channel KB5018482 https://support.microsoft.com/help/5018482 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5018482 242 | Version 21H2 (OS build 19044) 19044.2132 2022-10-17 False True LTSC • General Availability Channel KB5020435 https://support.microsoft.com/help/5020435 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5020435 243 | Version 21H2 (OS build 19044) 19044.2130 2022-10-11 False False LTSC • General Availability Channel KB5018410 https://support.microsoft.com/help/5018410 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5018410 244 | Version 21H2 (OS build 19044) 19044.2075 2022-09-20 True False LTSC • General Availability Channel KB5017380 https://support.microsoft.com/help/5017380 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5017380 245 | Version 21H2 (OS build 19044) 19044.2006 2022-09-13 False False LTSC • General Availability Channel KB5017308 https://support.microsoft.com/help/5017308 https://www.catalog.update.microsoft.com/Search.aspx?q=KB5017308 246 | ``` 247 | 248 | ## How to compare current vs latest OS build 249 | 250 | To compare you can use the following code example. This will compare a device's current OS build against the latest available OS build of Windows 10 22H2 (including out-of-band and excluding preview builds) this can be changed as required and guidance can be found above. The $Status variable can used in your RMM, monitoring solution or scripts as required. 251 | 252 | ```powershell 253 | $InstalledOSBuild = Get-CurrentOSBuild 254 | $LatestOSBuilds = Get-LatestOSBuild -OSName Win10 -OSVersion 22H2 -LatestReleases 1 -ExcludePreview 255 | 256 | If ($LatestOSBuilds -match $InstalledOSBuild) { 257 | Write-Output "OK - OS Build is up to date" 258 | $Status = "OK" 259 | } 260 | Else { 261 | Write-Output "Warning - OS Build is out of date" 262 | $Status = "Warning" 263 | } 264 | ```` 265 | 266 | ## Who 267 | 268 | This module is maintained by the following 269 | 270 | * Ashley How, [@AshleyHow1](https://twitter.com/AshleyHow1) 271 | 272 | ## Credits 273 | 274 | Forked from [Get-Windows10ReleaseInformation.ps1](https://github.com/FredrikWall/PowerShell/blob/master/Windows/Get-Windows10ReleaseInformation.ps1) created by [Fredrik Wall](https://github.com/FredrikWall) 275 | 276 | 277 | Uses code adapted from [Get-CurrentPatchInfo.ps1](https://gist.githubusercontent.com/SMSAgentSoftware/79fb091a4b7806378fc0daa826dbfb47/raw/0f6b52cddf82b2aa836a813cf6bc910a52a48c9f/Get-CurrentPatchInfo.ps1) created by [Trevor Jones](https://github.com/SMSAgentSoftware) 278 | 279 | [psgallery-badge]: https://img.shields.io/powershellgallery/v/WindowsOSBuild.svg?logo=PowerShell&style=flat-square 280 | [psgallery]: https://www.powershellgallery.com/packages/WindowsOSBuild 281 | [psgallery-version-badge]: https://img.shields.io/powershellgallery/dt/WindowsOSBuild.svg?logo=PowerShell&style=flat-square 282 | [license-badge]: https://img.shields.io/github/license/AshleyHow/WindowsOSBuild.svg?style=flat-square 283 | [license]: https://github.com/AshleyHow/WindowsOSBuild/blob/main/LICENCE 284 | -------------------------------------------------------------------------------- /WindowsOSBuild.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AshleyHow/WindowsOSBuild/e61d4f94fb16f00459182a90df07326bc0de0207/WindowsOSBuild.png -------------------------------------------------------------------------------- /WindowsOSBuild.psd1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AshleyHow/WindowsOSBuild/e61d4f94fb16f00459182a90df07326bc0de0207/WindowsOSBuild.psd1 -------------------------------------------------------------------------------- /WindowsOSBuild.psm1: -------------------------------------------------------------------------------- 1 | # Get public and private function definition files 2 | $Public = @(Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue) 3 | $Private = @(Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue) 4 | 5 | # Dot source the files 6 | Foreach($Import in @($Public + $Private)) { 7 | Try { 8 | . $Import.Fullname 9 | } 10 | Catch { 11 | Write-Error -Message "Failed to import function $(Import.Fullname): $_" 12 | } 13 | } 14 | 15 | # Export the public functions. This requires them to match the standard Noun-Verb powershell cmdlet format as a safety mechanism 16 | Export-ModuleMember -Function ($Public.Basename | Where-Object {$PSitem -match '^\w+-\w+$'}) 17 | # SIG # Begin signature block 18 | # MIImcgYJKoZIhvcNAQcCoIImYzCCJl8CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB 19 | # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR 20 | # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUzqz/GSkb7d7x8NKJYjIEpKgK 21 | # TO2ggiAtMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B 22 | # AQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD 23 | # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk 24 | # IElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQsw 25 | # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu 26 | # ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw 27 | # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz 28 | # 7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS 29 | # 5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7 30 | # bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfI 31 | # SKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jH 32 | # trHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14 33 | # Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2 34 | # h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt 35 | # 6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPR 36 | # iQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ER 37 | # ElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4K 38 | # Jpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAd 39 | # BgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SS 40 | # y4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAk 41 | # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAC 42 | # hjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS 43 | # b290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0 44 | # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRV 45 | # HSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyh 46 | # hyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO 47 | # 0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo 48 | # 8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++h 49 | # UD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5x 50 | # aiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMIIGYzCCBEug 51 | # AwIBAgIQeAuTgzemd0ILREkKU+Yq2jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQG 52 | # EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMSQwIgYDVQQD 53 | # ExtDZXJ0dW0gQ29kZSBTaWduaW5nIDIwMjEgQ0EwHhcNMjQwNDExMDYwMzIxWhcN 54 | # MjUwNDExMDYwMzIwWjCBiDELMAkGA1UEBhMCR0IxDzANBgNVBAgMBkRvcnNldDEU 55 | # MBIGA1UEBwwLQk9VUk5FTU9VVEgxHjAcBgNVBAoMFU9wZW4gU291cmNlIERldmVs 56 | # b3BlcjEyMDAGA1UEAwwpT3BlbiBTb3VyY2UgRGV2ZWxvcGVyLCBBU0hMRVkgTUlD 57 | # SEFFTCBIT1cwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDpmsgFPzl4 58 | # 7W61kLLEp5ljxHC0ZZDti0+DL2JSAac1+bQW24vSjg4ABHhRB5CDKBuwVe2h0l+G 59 | # mEZHhKc9cz/RB+hUIJycd5Qx6VzsI1KJ0heEECm+oo3rywyqrd9RovkhkU2X29cR 60 | # UAa9SWZJJ2+/ImyzfyxzR+u0DD17BucHXWylQB2HGFCcX3kYUmgyZ/ANrgTvetW+ 61 | # n91OLxquC5+Nslh4MhbQAnItX79qrFLODd05S3SpQvdti16WGcRwXka4t5zdAMf6 62 | # v3c8ThHKPm/1TsyWsYAUMYJ9C0sNt+QYKNYHRX7DuA1OJBngAyGggtaXmqEpPBX2 63 | # SkDJ0uOeVDoJEOsxNydGZYPgvkIzsyF8YmEzkPK5x5elglYI0wfGwaMKshVbszj5 64 | # KXIPogeF/0vrEi8iIEd+Ro3ZY8ul+TliYf6P55tl3VCuKHDbzcYCtOXURmAPGwxC 65 | # 9wVvTr946eJr+emejOxg4/BZw5Q5GD6Qr8wwyodqholbzp8bfjTFmC8CAwEAAaOC 66 | # AXgwggF0MAwGA1UdEwEB/wQCMAAwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2Nj 67 | # c2NhMjAyMS5jcmwuY2VydHVtLnBsL2Njc2NhMjAyMS5jcmwwcwYIKwYBBQUHAQEE 68 | # ZzBlMCwGCCsGAQUFBzABhiBodHRwOi8vY2NzY2EyMDIxLm9jc3AtY2VydHVtLmNv 69 | # bTA1BggrBgEFBQcwAoYpaHR0cDovL3JlcG9zaXRvcnkuY2VydHVtLnBsL2Njc2Nh 70 | # MjAyMS5jZXIwHwYDVR0jBBgwFoAU3XRdTADbe5+gdMqxbvc8wDLAcM0wHQYDVR0O 71 | # BBYEFB7BnDzi+HIrft6IpueXUsx5LcgwMEsGA1UdIAREMEIwCAYGZ4EMAQQBMDYG 72 | # CyqEaAGG9ncCBQEEMCcwJQYIKwYBBQUHAgEWGWh0dHBzOi8vd3d3LmNlcnR1bS5w 73 | # bC9DUFMwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDgYDVR0PAQH/BAQDAgeAMA0GCSqG 74 | # SIb3DQEBCwUAA4ICAQBO5qPmZq+cztnjKtz9DyVBkZGaHj/TmfIZHrYfeQ0zdEVL 75 | # EszgokLuqNDdk0odEUHiockPB2dQn60oE3rNs+Wb1ZLLT18VoQTV0saMD3GiNzil 76 | # ejD4nIrhQ+vt0auxCvzBS8cQd24ePmjTqcIkL/u07xGhtT3LpUHUuHknUcEFjgs0 77 | # bUpGR5bofW8B9ZSC31g2i5PKZH8PUgOrTvg8oaMQYWyduKFnW8JRRGqypjUIFDE0 78 | # N224ox/U6GqqIl2cuC87H7WrHPEO6VjqSOx0PgybhSggGDKRNk9UQN1R45K/NCcw 79 | # 5+sIA1pjTZHnMhIJdxamhXiNq2S0U3LRVLSs1/BuXGENFWUraE4c51kDCiBPpGus 80 | # olI7/LLF3PIyYopyAWOGw0R7snlT+HJbfI7P6ObfYzzmIMdrKSaBkNtautcRYcIT 81 | # HAmbUAVplnpexQXXapSqxUfrPXWZk7xRLSXXqn915NbAoofVrTuLNXbv437KmoaN 82 | # p2J23oE7KzqdkoZ9SO4+8K+XKoEqBrPyxNB/i5UIId1Rsu5GE453usJf7zgsz4Ib 83 | # T8MQXjPq0WageEH3cL3qoPGBVbD++hLCJhqHPFJfM3zqxz4xZIRm7dY7GmcVc3Qq 84 | # H0biPnYkTfe8fwrT/IpEmVPdDnUSM92MhV25HV4CYU5LAISU1B070DMFAGc1uTCC 85 | # Bq4wggSWoAMCAQICEAc2N7ckVHzYR6z9KGYqXlswDQYJKoZIhvcNAQELBQAwYjEL 86 | # MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 87 | # LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0 88 | # MB4XDTIyMDMyMzAwMDAwMFoXDTM3MDMyMjIzNTk1OVowYzELMAkGA1UEBhMCVVMx 89 | # FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVz 90 | # dGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTCCAiIwDQYJKoZI 91 | # hvcNAQEBBQADggIPADCCAgoCggIBAMaGNQZJs8E9cklRVcclA8TykTepl1Gh1tKD 92 | # 0Z5Mom2gsMyD+Vr2EaFEFUJfpIjzaPp985yJC3+dH54PMx9QEwsmc5Zt+FeoAn39 93 | # Q7SE2hHxc7Gz7iuAhIoiGN/r2j3EF3+rGSs+QtxnjupRPfDWVtTnKC3r07G1decf 94 | # BmWNlCnT2exp39mQh0YAe9tEQYncfGpXevA3eZ9drMvohGS0UvJ2R/dhgxndX7RU 95 | # CyFobjchu0CsX7LeSn3O9TkSZ+8OpWNs5KbFHc02DVzV5huowWR0QKfAcsW6Th+x 96 | # tVhNef7Xj3OTrCw54qVI1vCwMROpVymWJy71h6aPTnYVVSZwmCZ/oBpHIEPjQ2OA 97 | # e3VuJyWQmDo4EbP29p7mO1vsgd4iFNmCKseSv6De4z6ic/rnH1pslPJSlRErWHRA 98 | # KKtzQ87fSqEcazjFKfPKqpZzQmiftkaznTqj1QPgv/CiPMpC3BhIfxQ0z9JMq++b 99 | # Pf4OuGQq+nUoJEHtQr8FnGZJUlD0UfM2SU2LINIsVzV5K6jzRWC8I41Y99xh3pP+ 100 | # OcD5sjClTNfpmEpYPtMDiP6zj9NeS3YSUZPJjAw7W4oiqMEmCPkUEBIDfV8ju2Tj 101 | # Y+Cm4T72wnSyPx4JduyrXUZ14mCjWAkBKAAOhFTuzuldyF4wEr1GnrXTdrnSDmuZ 102 | # DNIztM2xAgMBAAGjggFdMIIBWTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW 103 | # BBS6FtltTYUvcyl2mi91jGogj57IbzAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/ 104 | # 57qYrhwPTzAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwdwYI 105 | # KwYBBQUHAQEEazBpMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j 106 | # b20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdp 107 | # Q2VydFRydXN0ZWRSb290RzQuY3J0MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9j 108 | # cmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3JsMCAGA1Ud 109 | # IAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEA 110 | # fVmOwJO2b5ipRCIBfmbW2CFC4bAYLhBNE88wU86/GPvHUF3iSyn7cIoNqilp/GnB 111 | # zx0H6T5gyNgL5Vxb122H+oQgJTQxZ822EpZvxFBMYh0MCIKoFr2pVs8Vc40BIiXO 112 | # lWk/R3f7cnQU1/+rT4osequFzUNf7WC2qk+RZp4snuCKrOX9jLxkJodskr2dfNBw 113 | # CnzvqLx1T7pa96kQsl3p/yhUifDVinF2ZdrM8HKjI/rAJ4JErpknG6skHibBt94q 114 | # 6/aesXmZgaNWhqsKRcnfxI2g55j7+6adcq/Ex8HBanHZxhOACcS2n82HhyS7T6NJ 115 | # uXdmkfFynOlLAlKnN36TU6w7HQhJD5TNOXrd/yVjmScsPT9rp/Fmw0HNT7ZAmyEh 116 | # QNC3EyTN3B14OuSereU0cZLXJmvkOHOrpgFPvT87eK1MrfvElXvtCl8zOYdBeHo4 117 | # 6Zzh3SP9HSjTx/no8Zhf+yvYfvJGnXUsHicsJttvFXseGYs2uJPU5vIXmVnKcPA3 118 | # v5gA3yAWTyf7YGcWoWa63VXAOimGsJigK+2VQbc61RWYMbRiCQ8KvYHZE/6/pNHz 119 | # V9m8BPqC3jLfBInwAM1dwvnQI38AC+R2AibZ8GV2QqYphwlHK+Z/GqSFD/yYlvZV 120 | # VCsfgPrA8g4r5db7qS9EFUrnEw4d2zc4GqEr9u3WfPwwgga5MIIEoaADAgECAhEA 121 | # maOACiZVO2Wr3G6EprPqOTANBgkqhkiG9w0BAQwFADCBgDELMAkGA1UEBhMCUEwx 122 | # IjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNl 123 | # cnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRy 124 | # dXN0ZWQgTmV0d29yayBDQSAyMB4XDTIxMDUxOTA1MzIxOFoXDTM2MDUxODA1MzIx 125 | # OFowVjELMAkGA1UEBhMCUEwxITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMg 126 | # Uy5BLjEkMCIGA1UEAxMbQ2VydHVtIENvZGUgU2lnbmluZyAyMDIxIENBMIICIjAN 127 | # BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnSPPBDAjO8FGLOczcz5jXXp1ur5c 128 | # Tbq96y34vuTmflN4mSAfgLKTvggv24/rWiVGzGxT9YEASVMw1Aj8ewTS4IndU8s7 129 | # VS5+djSoMcbvIKck6+hI1shsylP4JyLvmxwLHtSworV9wmjhNd627h27a8RdrT1P 130 | # H9ud0IF+njvMk2xqbNTIPsnWtw3E7DmDoUmDQiYi/ucJ42fcHqBkbbxYDB7SYOou 131 | # u9Tj1yHIohzuC8KNqfcYf7Z4/iZgkBJ+UFNDcc6zokZ2uJIxWgPWXMEmhu1gMXgv 132 | # 8aGUsRdaCtVD2bSlbfsq7BiqljjaCun+RJgTgFRCtsuAEw0pG9+FA+yQN9n/kZtM 133 | # LK+Wo837Q4QOZgYqVWQ4x6cM7/G0yswg1ElLlJj6NYKLw9EcBXE7TF3HybZtYvj9 134 | # lDV2nT8mFSkcSkAExzd4prHwYjUXTeZIlVXqj+eaYqoMTpMrfh5MCAOIG5knN4Q/ 135 | # JHuurfTI5XDYO962WZayx7ACFf5ydJpoEowSP07YaBiQ8nXpDkNrUA9g7qf/rCkK 136 | # bWpQ5boufUnq1UiYPIAHlezf4muJqxqIns/kqld6JVX8cixbd6PzkDpwZo4SlADa 137 | # Ci2JSplKShBSND36E/ENVv8urPS0yOnpG4tIoBGxVCARPCg1BnyMJ4rBJAcOSnAW 138 | # d18Jx5n858JSqPECAwEAAaOCAVUwggFRMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O 139 | # BBYEFN10XUwA23ufoHTKsW73PMAywHDNMB8GA1UdIwQYMBaAFLahVDkCw6A/joq8 140 | # +tT4HKbROg79MA4GA1UdDwEB/wQEAwIBBjATBgNVHSUEDDAKBggrBgEFBQcDAzAw 141 | # BgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vY3JsLmNlcnR1bS5wbC9jdG5jYTIuY3Js 142 | # MGwGCCsGAQUFBwEBBGAwXjAoBggrBgEFBQcwAYYcaHR0cDovL3N1YmNhLm9jc3At 143 | # Y2VydHVtLmNvbTAyBggrBgEFBQcwAoYmaHR0cDovL3JlcG9zaXRvcnkuY2VydHVt 144 | # LnBsL2N0bmNhMi5jZXIwOQYDVR0gBDIwMDAuBgRVHSAAMCYwJAYIKwYBBQUHAgEW 145 | # GGh0dHA6Ly93d3cuY2VydHVtLnBsL0NQUzANBgkqhkiG9w0BAQwFAAOCAgEAdYhY 146 | # D+WPUCiaU58Q7EP89DttyZqGYn2XRDhJkL6P+/T0IPZyxfxiXumYlARMgwRzLRUS 147 | # tJl490L94C9LGF3vjzzH8Jq3iR74BRlkO18J3zIdmCKQa5LyZ48IfICJTZVJeChD 148 | # UyuQy6rGDxLUUAsO0eqeLNhLVsgw6/zOfImNlARKn1FP7o0fTbj8ipNGxHBIutiR 149 | # sWrhWM2f8pXdd3x2mbJCKKtl2s42g9KUJHEIiLni9ByoqIUul4GblLQigO0ugh7b 150 | # WRLDm0CdY9rNLqyA3ahe8WlxVWkxyrQLjH8ItI17RdySaYayX3PhRSC4Am1/7mAT 151 | # wZWwSD+B7eMcZNhpn8zJ+6MTyE6YoEBSRVrs0zFFIHUR08Wk0ikSf+lIe5Iv6RY3 152 | # /bFAEloMU+vUBfSouCReZwSLo8WdrDlPXtR0gicDnytO7eZ5827NS2x7gCBibESY 153 | # kOh1/w1tVxTpV2Na3PR7nxYVlPu1JPoRZCbH86gc96UTvuWiOruWmyOEMLOGGniR 154 | # +x+zPF/2DaGgK2W1eEJfo2qyrBNPvF7wuAyQfiFXLwvWHamoYtPZo0LHuH8X3n9C 155 | # +xN4YaNjt2ywzOr+tKyEVAotnyU9vyEVOaIYMk3IeBrmFnn0gbKeTTyYeEEUz/Qw 156 | # t4HOUBCrW602NCmvO1nm+/80nLy5r0AZvCQxaQ4wggbCMIIEqqADAgECAhAFRK/z 157 | # lJ0IOaa/2z9f5WEWMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcwFQYD 158 | # VQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBH 159 | # NCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMjMwNzE0MDAwMDAw 160 | # WhcNMzQxMDEzMjM1OTU5WjBIMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNl 161 | # cnQsIEluYy4xIDAeBgNVBAMTF0RpZ2lDZXJ0IFRpbWVzdGFtcCAyMDIzMIICIjAN 162 | # BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAo1NFhx2DjlusPlSzI+DPn9fl0udd 163 | # oQ4J3C9Io5d6OyqcZ9xiFVjBqZMRp82qsmrdECmKHmJjadNYnDVxvzqX65RQjxwg 164 | # 6seaOy+WZuNp52n+W8PWKyAcwZeUtKVQgfLPywemMGjKg0La/H8JJJSkghraarrY 165 | # O8pd3hkYhftF6g1hbJ3+cV7EBpo88MUueQ8bZlLjyNY+X9pD04T10Mf2SC1eRXWW 166 | # df7dEKEbg8G45lKVtUfXeCk5a+B4WZfjRCtK1ZXO7wgX6oJkTf8j48qG7rSkIWRw 167 | # 69XloNpjsy7pBe6q9iT1HbybHLK3X9/w7nZ9MZllR1WdSiQvrCuXvp/k/XtzPjLu 168 | # UjT71Lvr1KAsNJvj3m5kGQc3AZEPHLVRzapMZoOIaGK7vEEbeBlt5NkP4FhB+9ix 169 | # LOFRr7StFQYU6mIIE9NpHnxkTZ0P387RXoyqq1AVybPKvNfEO2hEo6U7Qv1zfe7d 170 | # Cv95NBB+plwKWEwAPoVpdceDZNZ1zY8SdlalJPrXxGshuugfNJgvOuprAbD3+yqG 171 | # 7HtSOKmYCaFxsmxxrz64b5bV4RAT/mFHCoz+8LbH1cfebCTwv0KCyqBxPZySkwS0 172 | # aXAnDU+3tTbRyV8IpHCj7ArxES5k4MsiK8rxKBMhSVF+BmbTO77665E42FEHypS3 173 | # 4lCh8zrTioPLQHsCAwEAAaOCAYswggGHMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMB 174 | # Af8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMCAGA1UdIAQZMBcwCAYGZ4EM 175 | # AQQCMAsGCWCGSAGG/WwHATAfBgNVHSMEGDAWgBS6FtltTYUvcyl2mi91jGogj57I 176 | # bzAdBgNVHQ4EFgQUpbbvE+fvzdBkodVWqWUxo97V40kwWgYDVR0fBFMwUTBPoE2g 177 | # S4ZJaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNB 178 | # NDA5NlNIQTI1NlRpbWVTdGFtcGluZ0NBLmNybDCBkAYIKwYBBQUHAQEEgYMwgYAw 179 | # JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBYBggrBgEFBQcw 180 | # AoZMaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0 181 | # UlNBNDA5NlNIQTI1NlRpbWVTdGFtcGluZ0NBLmNydDANBgkqhkiG9w0BAQsFAAOC 182 | # AgEAgRrW3qCptZgXvHCNT4o8aJzYJf/LLOTN6l0ikuyMIgKpuM+AqNnn48XtJoKK 183 | # cS8Y3U623mzX4WCcK+3tPUiOuGu6fF29wmE3aEl3o+uQqhLXJ4Xzjh6S2sJAOJ9d 184 | # yKAuJXglnSoFeoQpmLZXeY/bJlYrsPOnvTcM2Jh2T1a5UsK2nTipgedtQVyMadG5 185 | # K8TGe8+c+njikxp2oml101DkRBK+IA2eqUTQ+OVJdwhaIcW0z5iVGlS6ubzBaRm6 186 | # zxbygzc0brBBJt3eWpdPM43UjXd9dUWhpVgmagNF3tlQtVCMr1a9TMXhRsUo063n 187 | # QwBw3syYnhmJA+rUkTfvTVLzyWAhxFZH7doRS4wyw4jmWOK22z75X7BC1o/jF5HR 188 | # qsBV44a/rCcsQdCaM0qoNtS5cpZ+l3k4SF/Kwtw9Mt911jZnWon49qfH5U81PAC9 189 | # vpwqbHkB3NpE5jreODsHXjlY9HxzMVWggBHLFAx+rrz+pOt5Zapo1iLKO+uagjVX 190 | # KBbLafIymrLS2Dq4sUaGa7oX/cR3bBVsrquvczroSUa31X/MtjjA2Owc9bahuEMs 191 | # 305MfR5ocMB3CtQC4Fxguyj/OOVSWtasFyIjTvTs0xf7UGv/B3cfcZdEQcm4RtNs 192 | # MnxYL2dHZeUbc7aZ+WssBkbvQR7w8F/g29mtkIBEr4AQQYoxggWvMIIFqwIBATBq 193 | # MFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMu 194 | # QS4xJDAiBgNVBAMTG0NlcnR1bSBDb2RlIFNpZ25pbmcgMjAyMSBDQQIQeAuTgzem 195 | # d0ILREkKU+Yq2jAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKA 196 | # ADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYK 197 | # KwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUMiQ7LoJU46oE44dXoVxv5KoLu/cw 198 | # DQYJKoZIhvcNAQEBBQAEggGA3IfoRHSyltE1h4/vEhF/WE3NCB6t5jqUB1S/CM4D 199 | # R33OtEfdmtJFTC9eItaA5ZibZbJFshcZw7vZw+qUBRbwZJIV0VocREF9OsXlLpNX 200 | # fl+C8OU2fibaQIm/qMKkNV83mIEJAzFj1sXoCAA7H/zD1caV6JzN/Mt57ZhC8MAk 201 | # xgaZgsN+6LgtPNd2i7MNZegvL2XnoGsu+uSPAEznp48APbcjBzTa1WF8A7CSSuO/ 202 | # xnSPSEoSCye8EO1YUY82DGwot9+eL0DMRHtDBv/4tWWFWKpCNa663G4gAnUIoIfC 203 | # F8IHrGN5W+atDQOszaxeWJusXoGsKgwUAdfhn/z0ONG7gXJ/wm02OujAji3pHzV5 204 | # Dx5XRHot3I5cmgbCn58n1jRULQGpJQSfhkAU5t8HK2T4Us0RhJTkIpw0ujHpr5b8 205 | # 035cbjCgX/FEr5UzGFMgBcPRpOTTTiXiAsEjPTz9cgYgcO0KrkFpX+15IFiL5uoG 206 | # YUjP7bSPhQzMYV61SR1pa6WdoYIDIDCCAxwGCSqGSIb3DQEJBjGCAw0wggMJAgEB 207 | # MHcwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYD 208 | # VQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFt 209 | # cGluZyBDQQIQBUSv85SdCDmmv9s/X+VhFjANBglghkgBZQMEAgEFAKBpMBgGCSqG 210 | # SIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTI0MDQyNDIyMDkx 211 | # OVowLwYJKoZIhvcNAQkEMSIEIOr+13rHw+1wenALIzPo80xx0o/73bna2pOzWzev 212 | # ArrLMA0GCSqGSIb3DQEBAQUABIICADgrDMZH7rQYzdrQLrqRsXOdxHFZACKemFUh 213 | # 90myhhBvBFNzgSY86HlJnIKOLY/YTdeva4OUTZ3xl601dSbYXLvCw2j96qPkDzQT 214 | # N7o7aw3iy9alTo7+KGRTEc0ZlJBpIXdKPYr9Pps2Bwavz0pIBYhIlo1LedR+4FZZ 215 | # JcnIEG7szHjOvEbx1kF2Iji/wqf9tZ0a8VTE0eXqnQ8L/T0KBqON3QsDeaFrzLDV 216 | # 6YcHcgo+W0FC9BFI+y2EZ3+MVpKhm5EHeM2C4lK7Smt+9YXr6o2MOGImWncmIDtM 217 | # ykyY7Y7pg4zrQ/bs9KYQvXaI5ZMu/dtYLeQ26xZY2k8Gkhi6vYBkcivcJUWZ9mlB 218 | # TVZUZ4cRs5XAcTa2GLyX8ZQNRQRK1s+hkU2tuN5XCdPF/x8J2RdBuPDcciJAWaOX 219 | # 0tvUEqlGycsJnqiy56IgwqFQOYt4lwZRuUDoHRO4102kdhT7KZOb1wEgwgC+45YT 220 | # vtlFOsmAbXPGvshZVvMbgKpks4UbRR+bAbYnndnttR9voLqMsbpC0ZAjP+HNdN9n 221 | # AjZjgdct/yDxKqI9/0lfb+sdhNTfqMm5ZfgnCE5annYzsy0n/lFYv1uLzW1yGpHO 222 | # ZnuYdnb57t2SjbWPe1rkOGdnn5/FhPCMrLCv7pw/BcGj517LAzAAuigi0qaOJ8iR 223 | # UKQs1CIJ 224 | # SIG # End signature block 225 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | skip_commits: 2 | files: 3 | - "**/*.md" 4 | - "**/*.png" 5 | - "**/*LICENCE" 6 | - "CI/WindowOSBuild.Tests.ps1" 7 | - "**/WindowsOSBuild.psd1" 8 | 9 | install: 10 | - ps: | 11 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 12 | Install-Module Pester -Force 13 | - pwsh: | 14 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 15 | Install-Module Pester -Force 16 | 17 | build: off 18 | 19 | test_script: 20 | - ps: | 21 | Import-Module -Name "Pester" -Force 22 | Import-Module -Name "C:\projects\windowsosbuild" 23 | $testResultsFile = ".\TestsResults_PS.xml" 24 | $ResultsPS = Invoke-Pester -OutputFormat NUnitXml -OutputFile $testResultsFile -Show All -PassThru 25 | (New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path $testResultsFile)) 26 | If ($ResultsPS.FailedCount -gt 0) { 27 | throw "$($res.FailedCount) tests failed." 28 | } 29 | - pwsh: | 30 | Import-Module -Name "Pester" -Force 31 | Import-Module -Name "C:\projects\windowsosbuild" 32 | $testResultsFile = ".\TestsResults_PWSH.xml" 33 | $ResultsPWSH = Invoke-Pester -OutputFormat NUnitXml -OutputFile $testResultsFile -Show All -PassThru 34 | (New-Object 'System.Net.WebClient').UploadFile("https://ci.appveyor.com/api/testresults/nunit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path $testResultsFile)) 35 | If ($ResultsPWSH.FailedCount -gt 0) { 36 | throw "$($res.FailedCount) tests failed." 37 | } 38 | -------------------------------------------------------------------------------- /lib/HtmlAgilityPack-1.12.0.0-net40-client.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AshleyHow/WindowsOSBuild/e61d4f94fb16f00459182a90df07326bc0de0207/lib/HtmlAgilityPack-1.12.0.0-net40-client.dll -------------------------------------------------------------------------------- /lib/HtmlAgilityPack-1.12.0.0-netstandard2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AshleyHow/WindowsOSBuild/e61d4f94fb16f00459182a90df07326bc0de0207/lib/HtmlAgilityPack-1.12.0.0-netstandard2.dll -------------------------------------------------------------------------------- /lib/HtmlAgilityPack.LICENCE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Permission is hereby granted, free of charge, to any person obtaining a copy 3 | of this software and associated documentation files (the Software), to deal 4 | in the Software without restriction, including without limitation the rights 5 | to use, copy, modify, merge, publish, distribute, sublicense, andor sell 6 | copies of the Software, and to permit persons to whom the Software is 7 | furnished to do so, subject to the following conditions 8 | 9 | The above copyright notice and this permission notice shall be included in all 10 | copies or substantial portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 18 | SOFTWARE. --------------------------------------------------------------------------------