# Windows Server 2016 End of Support: How to Check Dates and Plan Migration

> AI Release · @ai_release1 · https://ai-release.org/guides/windows-server-2016-zakanchivaet-podderzhku-kak-proveri_en.html

## TL;DR
- **Time to complete:** 60–90 minutes for the audit itself (inventory of your Windows Server 2016 hosts); the migration plan is written afterwards and depends on how many roles you find.
- **Difficulty:** Intermediate — you need PowerShell, remote management (WinRM), and read access to Active Directory.
- **You will need:**
  - One Windows Server 2016 host to test the commands on, plus a management workstation with Windows PowerShell 5.1.
  - A domain account that is a local administrator on the target servers and has read rights in AD.
  - RSAT Active Directory PowerShell module on the workstation (`Get-ADComputer`).
  - WinRM enabled on the servers (TCP 5985/5986) or console/RDP access as a fallback.
  - A folder for output, for example `C:\Inventory\`.
  - Access to the official Microsoft Lifecycle Policy page for Windows Server 2016 (open it yourself and copy the dates — do not trust second-hand blog posts).

## Requirements and setup
![Illustration: Requirements and setup](https://ai-release.org/guides/img/windows-server-2016-zakanchivaet-podderzhku-kak-proveri-en-1.jpg?v=1792833147)

- **OS under audit:** Windows Server 2016, any edition. The build number family is `14393`; patched servers still report `14393` with a higher revision.
- **Management workstation:** Windows 10/11 or Windows Server with Windows PowerShell 5.1 (`$PSVersionTable.PSVersion` must show `5.1.x`). PowerShell 2.0 will fail on the cmdlets below.
- **Permissions:** local administrator on every server you query, plus `Domain Users` (or delegated read) for the AD query. Remote inventory needs WinRM, which is not enabled by default on all images.
- **Network ports:** TCP 5985 (WinRM HTTP) or 5986 (WinRM HTTPS) from the workstation to each server; TCP 8530/8531 if you also check WSUS — Windows Server Update Services, the internal patch server.
- **Disk space:** negligible — the CSVs produced here are a few hundred KB for a few hundred servers.
- **Terminology you will meet:** *ESU* — Extended Security Updates, a paid programme that can keep an out-of-support product patched; *CIM* — the standard Windows interface PowerShell uses to read hardware/OS data; *FSMO* — the five special AD roles held by specific domain controllers.

Create the working folder first:

```powershell
New-Item -ItemType Directory -Path C:\Inventory -Force
```

## Step 1. Record the official support dates and the current build of every host

**What to do:** Open the Microsoft Lifecycle Policy page for **Windows Server 2016** in a browser, and copy three things into `C:\Inventory\lifecycle.md`: the mainstream end date, the extended end date, and the exact wording of the Extended Security Updates section. Then read the OS identity from a representative server.

```powershell
Get-CimInstance Win32_OperatingSystem |
  Select-Object Caption, Version, BuildNumber, InstallDate, LastBootUpTime |
  Format-List
```

**Example output** (values differ per host — the build family is what matters):

```
Caption        : Microsoft Windows Server 2016 Standard
Version        : 10.0.14393
BuildNumber    : 14393
InstallDate    : 11/14/2017 09:12:44
LastBootUpTime : 03/02/2025 06:01:10
```

**Why:** the lifecycle dates are published per product and per edition, and the build number tells you the patch baseline. `10.0.14393` identifies Windows Server 2016; the last four digits never change, so a server that has never been patched and one patched last month look identical here — which is exactly why you record the hotfix level in Step 3. If you also maintain Windows client machines, the same "check the vendor page, then check the machine" method is described in [How to Check When Your Windows PC Will Stop Receiving Updates](https://ai-release.org/guides/kak-proverit-kogda-vash-pk-s-windows-perestanet-polucha.html?utm_source=tg&utm_medium=channel&utm_campaign=guide_inline&utm_content=guide_to_guide).

**How to check:** run `winver` on the same server. The dialog must show "Windows Server 2016" and the same build number as `BuildNumber` above. In `lifecycle.md` you must have three filled lines, each with the date you checked the page — for example `extended_end: <date from the page> (checked 2025-XX-XX)`. If a line is empty, the plan is not grounded and you must go back to the page; the exact date is not hard-coded in this guide on purpose — **verify it in the official documentation**.

## Step 2. Build the inventory: which servers, which roles, which owner
![Illustration: Step 2. Build the inventory: which servers, which roles, which owner](https://ai-release.org/guides/img/windows-server-2016-zakanchivaet-podderzhku-kak-proveri-en-2.jpg?v=1792833162)


**What to do:** pull every computer object whose operating system string mentions Windows Server 2016, then collect installed roles from each host over WinRM.

```powershell
Get-ADComputer -Filter 'OperatingSystem -like "*Windows Server 2016*"' `
  -Properties OperatingSystem, OperatingSystemVersion, LastLogonDate, DistinguishedName |
  Select-Object Name, OperatingSystem, OperatingSystemVersion, LastLogonDate, DistinguishedName |
  Sort-Object LastLogonDate |
  Export-Csv C:\Inventory\ws2016-servers.csv -NoTypeInformation -Encoding UTF8
```

**Example row** you should see in the CSV:

```
"SRV-FS01","Windows Server 2016 Standard","10.0.14393","02/28/2025 21:40:11","CN=SRV-FS01,OU=FileServers,DC=contoso,DC=com"
```

Now collect the roles, because the migration path depends on them:

```powershell
$servers = Import-Csv C:\Inventory\ws2016-servers.csv | Select-Object -ExpandProperty Name

Invoke-Command -ComputerName $servers -ErrorAction Continue -ScriptBlock {
  [pscustomobject]@{
    Server    = $env:COMPUTERNAME
    Roles     = (Get-WindowsFeature | Where-Object Installed |
                 Select-Object -ExpandProperty Name) -join ';'
    PSVersion = $PSVersionTable.PSVersion.ToString()
  }
} | Select-Object Server, Roles, PSVersion |
  Export-Csv C:\Inventory\ws2016-roles.csv -NoTypeInformation -Encoding UTF8
```

**Why:** a file server, a domain controller and an IIS web host cannot be replaced by the same procedure. `Get-WindowsFeature` lists installed roles and features on a server OS; capturing it once gives you the raw material for migration waves. Fill the "owner" and "business function" columns by hand — AD cannot tell you who cares about the machine.

| Role found in `Roles` | What to record before planning | Why it blocks a naive "rebuild the box" |
|---|---|---|
| `AD-Domain-Services` | Whether it holds FSMO roles (`netdom query fsmo`) | You must add a new DC, transfer roles, then demote — never rebuild in place |
| `DNS`, `DHCP` | Zone/scopes export, DHCP reservations | Clients lose name resolution or leases during cutover |
| `File-Services` | Share list, NTFS permissions, total size | Data copy window defines the maintenance window |
| `Web-Server` | Sites, bindings, certificates | TLS certificates must be re-issued or exported |
| Anything else | Vendor product name and support contact | Third-party software may not be certified on the new OS |

**How to check:** count the rows and compare with the AD query result.

```powershell
(Import-Csv C:\Inventory\ws2016-servers.csv).Count
(Import-Csv C:\Inventory\ws2016-roles.csv).Count
```

Both numbers must match. If the second is smaller, some hosts did not answer over WinRM — see Troubleshooting. Then complete this checklist before moving on:

- [ ] Every host has a build number and a `LastLogonDate`.
- [ ] Every host has a role list (or is explicitly marked "unreachable — checked via console").
- [ ] Every host has an owner and a business function.
- [ ] Inbound dependencies recorded (who connects to it, on which port).
- [ ] Lifecycle dates copied from the vendor page with the check date.

## Step 3. Verify the patch channel and dry-run one low-risk server
![Illustration: Step 3. Verify the patch channel and dry-run one low-risk server](https://ai-release.org/guides/img/windows-server-2016-zakanchivaet-podderzhku-kak-proveri-en-3.jpg?v=1792833172)


**What to do:** confirm each server can still receive updates through your patch infrastructure, then pick one low-risk host (a test or secondary file server) and stand up its replacement, running the same commands against it.

```powershell
Get-HotFix | Sort-Object InstalledOn -Descending |
  Select-Object -First 5 HotFixID, Description, InstalledOn

Test-NetConnection <your-wsus-server> -Port 8530
```

**Example output:**

```
HotFixID  Description      InstalledOn
--------  -----------      -----------
KB50XXXXX Security Update  02/14/2025 00:00:00
KB50XXXXX Update           01/09/2025 00:00:00

ComputerName     : <your-wsus-server>
RemotePort       : 8530
TcpTestSucceeded : True
```

**Why:** the `InstalledOn` column proves the server is actually patched, not just "supposed to be". `TcpTestSucceeded : True` proves the path to the patch server is open, so any later failure is configuration, not the network. Run the identical `Get-CimInstance Win32_OperatingSystem` query on the replacement host: a different `Version` line (not `10.0.14393`) confirms the new OS is in place before you move data.

**How to check:** on the pilot replacement, `Get-WindowsFeature | Where-Object Installed` must list at least the roles the old host had, and the application must pass its own smoke test (open the share, browse the site, query the database). Record the result as a line in your wave table:

| Wave | Servers | Criteria | Exit check |
|---|---|---|---|
| 1 | Test/secondary hosts | No FSMO roles, no customer-facing SLA | Replacement responds, `Get-HotFix` returns a recent KB |
| 2 | File, print, IIS | Data copy tested | Shares and bindings identical |
| 3 | DNS, DHCP, domain controllers | Maintenance window agreed | `netdom query fsmo` shows the new holder |

## Troubleshooting

**Problem. The AD query fails immediately on the workstation.**
- Error: `Get-ADComputer : The term 'Get-ADComputer' is not recognized as the name of a cmdlet, function, script file, or operable program.`
- Cause: the RSAT Active Directory PowerShell module is not installed, or you are in a 32-bit PowerShell session.
- Solution: on Windows Server run `Install-WindowsFeature RSAT-AD-PowerShell`; on Windows 10/11 run `Add-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0`. Reopen PowerShell and confirm with `Get-Command Get-ADComputer` — it must return the `Cmdlet` entry.

**Problem. The remote role inventory returns nothing for some servers.**
- Error: `Connecting to remote server SRV-FS01 failed with the following error message : WinRM cannot complete the operation. Verify that the specified computer name is valid, that the computer is accessible over the network, and that a firewall exception for the WinRM service is enabled and allows access from the current computer.`
- Cause: WinRM is not configured on the target, or the firewall rule for TCP 5985 is disabled.
- Solution: on the target (via RDP or console) run `Enable-PSRemoting -Force` then `winrm quickconfig`. From the workstation verify with `Test-WSMan SRV-FS01` — you should see `wsmid`, `ProtocolVersion` and `ProductVersion` in the output. Only then re-run the `Invoke-Command` block.

**Problem. A server reports a patch error instead of a hotfix list.**
- Error: `Windows Update failed with error 0x8024401C`
- Cause: the client cannot reach the WSUS endpoint — wrong GPO value, closed port, or proxy.
- Solution: check `Test-NetConnection <your-wsus-server> -Port 8530`; read the effective policy with `gpresult /h C:\Inventory\rsop.html` and look for `WUServer` under `HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate`; restart the client with `net stop wuauserv` then `net start wuauserv`, and re-run the detection.

## Summary and next steps
You now have three artefacts: vendor lifecycle dates with the check date, a CSV inventory of every Windows Server 2016 host with its roles and owner, and a validated patch path plus one successful pilot replacement. Next, assign each host to a wave in the table above, book maintenance windows, and — if the refresh also covers desktops — follow [How to Install Windows 11 26H2: Step-by-Step Guide with Official ISO](https://ai-release.org/guides/kak-ustanovit-windows-11-26h2-poshagovaya-instruktsiya.html?utm_source=tg&utm_medium=channel&utm_campaign=guide_inline&utm_content=guide_to_guide) for the client side.

## FAQ

**When exactly does Windows Server 2016 support end?**
Microsoft publishes the mainstream end date and the extended end date on the product's Lifecycle Policy page. Open that page, copy both dates and the ESU wording into your plan with the date you checked — the exact value is deliberately not hard-coded here, so **verify it in the official documentation** rather than in a blog.

**Do security updates stop completely after the end date?**
Extended Security Updates (ESU) is the vendor programme that can keep an out-of-support product patched. Eligibility, delivery channel and pricing change per product and per year — confirm them on the official page before you budget anything.

**Can I just rebuild the domain controller like a file server?**
No. Add a new domain controller running a supported OS, wait for replication (`repadmin /replsummary` must show no failures), transfer the FSMO roles (`netdom query fsmo` before and after), and only then demote the old one.

**How long will the whole migration take?**
The audit in this guide takes 60–90 minutes. The migration itself depends on the roles you found in Step 2 and on your maintenance windows — there is no universal figure, so build the schedule from your own wave table.
