What kind of server channel are your running on: SAC or LTS?

  • Context:

I installed a SAC (Semi Annual Channel) based server and wanted to know what’s the difference with the LTS (Long Term Support) branch?


Source: https://docs.microsoft.com/en-us/windows-server/get-started-19/servicing-channels-19
There’s only 18 months support for the SAC channel.
There’s no upgrade path between branches, so you need to install from scratch when you want to move to a new branch.
That’s a big the deal.
I also wanted to have some code that would help me differentiate these 2 channels?

  • Solution:

I started to dig in google and the registry. I found this relevant info:

Source: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/hh846315(v=vs.85)

The WMI repository can help and contains the following:

Get-CimInstance -Property Caption -ClassName Win32_OperatingSystem |
Select -expand Caption



NB: Notice the year in the caption name before the edition (ex: Standard or Datacenter)
When the server is on a LTS channel, the year is specified whereas when on a SAC channel, it’s absent.

While there is a Get-ComputerInfo cmdlet, it doesn’t meet my needs. I wrote another function

Function Get-ServerInfo {
[CmdletBinding()]
Param()
Begin {
try {
$cv = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -ErrorAction 'Stop'
} catch {
Throw "Failed to read the registry because $($_.Exception.Message)"
}
}
Process {
try {
if ($cv.InstallationType -match 'Server') {
[PSCustomObject]@{
Branch = $(if($cv.ReleaseId){$cv.ReleaseId} else { $cv.CurrentVersion })
ProductName = $cv.ProductName
Build = $cv.CurrentBuild
Revision = $cv.UBR
Channel = $(if ($cv.ProductName -notmatch '\s\d{4}\s') { 'Semi-Annual Channel (SAC)' } else { 'Long Term Support (LTS)' })
isSAC = $(if ($cv.ProductName -match '\s\d{4}\s') { $false } else { $true })
isLTS = $(if ($cv.ProductName -notmatch '\s\d{4}\s') { $false } else { $true })
} |
Add-Member -MemberType ScriptProperty -Name isExpired -Value {
$y,$m = $this.Branch -split '(?<=\G.{2})'
if($this.isSAC -and ((Get-Date) -gt ((Get-Date -Year "20$($y)" -Month "$($m)").AddMonths(18)))) {
$true
} else {
$false
}
} -Force -PassThru -ErrorAction 'Stop'
}
} catch {
Throw "Failed to get server info because $($_.Exception.Message)"
}
}
End {}
<#
.SYNOPSIS
Get information about the server branch, channel, build,...
.DESCRIPTION
Get information about the server:
branch,
channel (SAC = Semi Annual Channel or LTS = Long Term Support)
build
revision,
product name
by reading the registry key
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion
.EXAMPLE
Get-ServerInfo
Branch : 1809
ProductName : Windows Server 2019 Datacenter
Build : 17763
Revision : 437
Channel : Long Term Support (LTS)
isSAC : False
isLTS : True
isExpired : False
.EXAMPLE
Get-ServerInfo
Branch : 1709
ProductName : Windows Server Datacenter
Build : 16299
Revision : 1087
Channel : Semi-Annual Channel (SAC)
isSAC : True
isLTS : False
isExpired : True
.EXAMPLE
Get-ServerInfo
Branch : 1903
ProductName : Windows Server Standard
Build : 18362
Revision : 113
Channel : Semi-Annual Channel (SAC)
isSAC : True
isLTS : False
isExpired : False
.EXAMPLE
Get-ServerInfo
Branch : 6.3
ProductName : Windows Server 2012 R2 Standard
Build : 9600
Revision : 19356
Channel : Long Term Support (LTS)
isSAC : False
isLTS : True
isExpired : False
#>
}
view raw Get-ServerInfo.ps1 hosted with ❤ by GitHub

The isExpired property is only valid for the SAC channel. I should modify the code accordingly in a further release.
If you run on the LTS channel, I would recommend that you use the official info on this site: https://support.microsoft.com/en-us/lifecycle/search

Let’s see the above function in action:

On a Windows server 2016

On a Windows server 2019

On a Windows Server 1903

On a Windows Server 1709

Notice that this SAC channel is expired

On a Windows 2012 R2 Server

Again, the LTS channel have an expiry date specified on this site: https://support.microsoft.com/en-us/lifecycle/search