The Exchange Server Health Checker is a free Microsoft script that compares a server against a long list of configuration problems known to cause performance issues, outages and security gaps. It should be the first thing you run before an upgrade and after every patch cycle. In this post I'll show where to get it, how to run it across all servers and build the HTML report, and how to fix the findings that come up most often.
Prerequisites#
- Supported versions: Exchange Server 2016, 2019 and Subscription Edition (SE).
- Permissions: local Administrator on the servers and membership of Organization Management. Domain Admins is needed only for the
-DCCoreRatiocheck. - Where to run it: an elevated Exchange Management Shell on an Exchange server.
- The script: download
HealthChecker.ps1from the "Download the latest release" link on the Health Checker page of Microsoft's CSS-Exchange project. Avoid copies from blogs or old file shares.
Step-by-step: run the checks and build the report#
1. Keep the script current#
Health Checker looks for a newer version each time it runs. For servers without internet access, refresh it on a machine that has access (the update switch doesn't need EMS or elevation) and copy it across:
.\HealthChecker.ps1 -ScriptUpdateOnlyThe security checks are only as current as the script, so an old copy can report "all good" on a server that is missing recent fixes.
2. Check one server#
.\HealthChecker.ps1 # local server
.\HealthChecker.ps1 -Server EX01 # a specific serverResults appear on screen, colour-coded (red for errors, yellow for warnings), and are saved as a log and an XML data file in the current folder, or in the folder you pass to -OutputFilePath.
3. Check every server and build the HTML report#
Get-ExchangeServer | Where-Object { $_.AdminDisplayVersion -Match "^Version 15" } | .\HealthChecker.ps1
.\HealthChecker.ps1 -BuildHtmlServersReport -HtmlReportFile "ExchangeAllServersReport.html"
.\ExchangeAllServersReport.htmlThe HTML report puts all servers side by side, which makes configuration drift easy to spot. If the XML files are elsewhere, add -XMLDirectoryPath. With -AnalyzeDataOnly you can analyse XML files that were collected earlier.
4. Use the extra reports when you need them#
-VulnerabilityReportcollects vulnerability information for all servers and exports it to JSON, which is handy for security teams.-MailboxReport -Server EX01produces a mailbox report for a single server.-LoadBalancingReport -SiteName SiteAshows how client connections are spread across servers.-DCCoreRatiocompares Exchange and domain controller cores in the current site.
Fixing the most common findings#
| Finding | Why it matters | Fix |
|---|---|---|
| Build out of date, or vulnerabilities listed in the Security Vulnerability section | The server is missing published security fixes | Install the latest Security Update for your CU (see my security update guide) |
| Pending reboot | Updates and Setup can fail or behave unpredictably | Restart in a maintenance window, then re-run the check |
| Power plan isn't High performance | CPU throttling adds latency | Set the High performance plan (below) and check the BIOS power profile |
| Page file managed by the system, the wrong size, or more than one page file | A known cause of performance problems on Exchange servers | One static page file, minimum = maximum: 25% of RAM on 2019 and SE; RAM + 10 MB (capped at 32,778 MB) on 2016 |
| TCP KeepAliveTime not set | Windows then waits two hours, and firewalls or load balancers may drop idle sessions first | Set 30 minutes (1800000 ms) |
| TLS settings inconsistent | Failed connections; Extended Protection depends on consistent TLS | Match the Client and Server values for each protocol, and set SystemDefaultTlsVersions and SchUseStrongCrypto to 1 for .NET 4 (64-bit and Wow6432Node keys) |
| Extended Protection not configured, or SSL offloading on Outlook Anywhere | Leaves the server open to authentication relay attacks | Fix TLS first, set -SSLOffloading $false with Set-OutlookAnywhere, then run Microsoft's ExchangeExtendedProtectionManagement.ps1 |
| Download Domains not configured | OWA attachments are served from the main OWA host name | Configure a separate download host name (below) |
| SMB1 installed or Credential Guard enabled | SMB1 is an unnecessary legacy protocol; Credential Guard isn't supported on Exchange | Remove SMB1 and turn off Credential Guard |
Host settings: power plan, KeepAlive and page file#
powercfg /setactive SCHEME_MIN
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" `
-Name KeepAliveTime -PropertyType DWord -Value 1800000 -Force
# Page file for a 2019/SE server with 128 GB RAM (25% = 32768 MB)
wmic ComputerSystem set AutomaticManagedPagefile=False
wmic PageFileSet set InitialSize=32768,MaximumSize=32768SCHEME_MIN is the built-in alias for High performance. If WMIC isn't available, set the page file under System Properties › Advanced › Performance Settings › Advanced › Virtual memory. The KeepAlive and page file changes need a restart.
Download Domains#
Get-OwaVirtualDirectory | Set-OwaVirtualDirectory -ExternalDownloadHostName download.contoso.com `
-InternalDownloadHostName download.contoso.com
Set-OrganizationConfig -EnableDownloadDomains $trueCreate the DNS record first and make sure the host name is on your Exchange certificate, or OWA attachments will stop opening.
Verify the fixes#
Re-run the script on every server and rebuild the HTML report. Good looks like:
- No red entries, and every remaining yellow warning is understood and documented.
- The Security Vulnerability section reports no known issues and the build shows the latest Security Update.
- Power plan, page file, KeepAlive and TLS values are identical across servers in the HTML report.
- Extended Protection is shown as configured, and OWA, Outlook and mobile clients still connect.
Tips and gotchas#
- Run it after every update cycle, not just once. Updates, new servers and well-meant manual changes all cause drift.
- Batch the restarts. Many host fixes need a reboot, so group them and use DAG maintenance mode as described in my in-place upgrade walkthrough.
- Order matters for Extended Protection. Enabling it with inconsistent TLS or SSL offloading still in place breaks client connections.
- Keep the XML files. They give you a before-and-after record for change management and audits.
- Before upgrading to SE, clear the red findings first; see the SE planning guide.

