Free tool · PowerShell

MECM Health Check

Where your ConfigMgr site stands — in one report, without changing a thing.

A read-only PowerShell script that reads your Configuration Manager site, its site systems, its clients and the hardening of every server, then writes a self-contained HTML report: what is fine, what is not, and what to fix first. The code is published below in full, to be read before it is run.

Read-onlynothing is changed
PowerShell 5.1+no module required
≈ 3 minfor a typical site
0 uploadthe report stays with you

What you get

One report, seven tabs.

One HTML file with no dependencies: it opens in any browser, can be emailed and archived. Every check says what it measured, why it matters and where Microsoft's documentation is.

Overview

The compliance rate, critical findings first, and the priorities in the order to tackle them.

Servers

Every site system with its roles, disk space, version and failing or stopped components.

Clients

Coverage, inactive devices, stale policy and inventory, client versions, co-management and workloads, enrolment errors.

Health check

The site, its components, deployments, content distribution, update sync, ADRs, collections and status messages.

Site security

Full administrators, network access account, client push, PXE, boundaries too wide or orphaned, task sequences — against the Misconfiguration Manager guidance.

Server hardening

On every server: shares, local accounts, passwords, services, SMB, NTLM, LLMNR, RDP, WinRM, Defender, Credential Guard, LAPS, logging, TLS.

Troubleshooting

The Configuration Manager logs of every server, read over seven days: errors grouped by probable cause, with what to do, a timeline, and the status messages component by component.

Before you start

Prerequisites.

The bare minimum is short: PowerShell and a read-only account on the site. The rest unlocks parts of the report — without it, the script says so and carries on.

RequirementForNotes
RequiredWindows PowerShell 5.1 or PowerShell 7The whole script.Built into Windows Server 2016 and later.
RequiredAn account with at least the Read-only Analyst role on the siteReading the site, its servers and its clients.The current account, or another through -Credential. ConfigMgr recognises an administrator by its SID, not its name: an account deleted then recreated under the same name has no rights at all, even though the console still lists it. The site then answers without showing anything, and the script stops and says so — recreate the administrative user.
RequiredA machine that can reach the SMS ProviderWhere every read goes.The site server itself, or any domain machine that can reach it: HTTPS 443 (AdminService), otherwise WMI over WinRM (5985), otherwise over DCOM (135 + dynamic ports).
OptionalThe AdminService enabledThe fastest reads.Without it, automatic fallback to WMI. Same report.
OptionalWinRM (5985/5986) to every site system, and local administratorThe Server hardening and Troubleshooting tabs.Or a JEA endpoint (-HardeningEndpoint). Without access: tab marked "not collected", or -SkipHardening / -SkipLogs.
OptionalA PowerShell console run as administratorHardening of the local machine.Local registry, services and password policy.
OptionalAn execution policy that allows a local scriptRunning the file.RemoteSigned is enough for a file created on the machine. Otherwise, for this session only: Set-ExecutionPolicy -Scope Process Bypass.
No module to install

The script uses neither the ConfigurationManager module nor the console: it reads the AdminService over HTTPS, or WMI, with commands that ship with Windows. Nothing is installed, neither on the machine running it nor on the audited servers.

Transparency

What it reads. What it writes. What it never does.

An audit that changes what it audits is no longer an audit. Every statement below can be checked in the code, further down.

It reads

  • The site: 23 WMI classes of the SMS Provider — site, components, roles, boundaries, deployments, content, updates, collections, status messages, administrators, boot images, and the site control file settings: client push, Network Access Account, communication security.
  • The clients: the device inventory and its co-management state.
  • Every server: registry keys, services, local groups, shares with their share and NTFS permissions, the Extended Protection of SQL Server instances, the client cache permissions and network settings.
  • The directory: one value only, the domain's machine account quota (ms-DS-MachineAccountQuota), over LDAP and read only.
  • The Configuration Manager logs of every server: only their end, only the error and warning lines, opened shared so the component writing them is never disturbed.

It writes

  • The HTML report, in the current folder or wherever -OutFile says.
  • A JSON of the data read, if you ask for it (-ExportJson).
  • On each audited server, a temporary hc_secpol_<guid>.cfg file in the account's temporary folder, produced by secedit /export, read then deleted at once — Windows has no other way to read the password policy. -SkipSecedit to create nothing at all.
  • With the options window, in the temporary folder of the machine running it: a progress file and — if you enter another account there — that account encrypted by Windows (DPAPI, readable only by you on that machine), deleted as soon as it has been read.

It never

  • Changes a setting, a deployment, a collection or a device: towards the site it only sends reads (GET requests to the AdminService, Get-CimInstance over WMI).
  • Starts, stops or reconfigures a service, or changes a permission, a registry key, an account or a directory value.
  • Installs anything, locally or remotely.
  • Calls the Internet: no request leaves your network. The report's links point to Microsoft Learn and only open if you click them.
  • Sends anything to LB IT Cloud. There is no telemetry, no licence, no account.

The traces it leaves

Nothing is changed, but a read shows, like that of any administrator looking around:

  • network logons in the servers' Windows security log;
  • the requests in smsprov.log and, for the AdminService, in the IIS logs;
  • the collector's text in the PowerShell logs, when script block logging is on;
  • the account's profile on each audited server, which PowerShell Remoting creates at the first session if it did not exist;
  • a line in secedit's own log (%windir%\security\logs).

To run nothing at all on the servers and read the site only: -SkipHardening -SkipLogs.

How to use it

Copy, paste, run.

1

Copy

The Copy the script button below copies the exact text — or read it first, section by section.
2

Paste and save

Into Notepad, VS Code or the ISE, on the site server or on a domain machine that can reach it. Save it as Invoke-MecmHealthCheck.ps1. The file is ASCII: whatever encoding you save it in makes no difference.
3

Run

In a PowerShell console run as administrator:
.\Invoke-MecmHealthCheck.ps1
With no parameter, a window opens: site, account, what is read, report folder — then it follows the run and opens the report at the end. From a command line, nothing is shown:
.\Invoke-MecmHealthCheck.ps1 -Client "Contoso" -Open

Parameters

-SiteServerThe SMS Provider to query. Default: this machine.
-SiteCodeSite code. Discovered automatically when omitted.
-SourceAuto (AdminService then WMI), AdminService or Wmi.
-CredentialAnother account for the site and for hardening.
-MessageHoursStatus message window, 0 to 168 h. Default: 24.
-HistoryDaysError message history read to date each component, 0 to 90 days. Default: 30.
-LogDays / -MaxLogMBHow far back the servers' logs are read (0 to 60 days, default 7) and how much of the end of each is read (default 5 MB).
-SkipLogsSkips the servers' logs.
-SkipClientsSkips the clients.
-SkipHardeningSkips hardening collection.
-HardeningHostsLimits hardening to these machines.
-SkipSeceditCreates no file, not even a temporary one, on the servers.
-ScanSharesAlso looks for sensitive files (passwords, .kdbx, unattend.xml) in the shares.
-Languagefr (default) or en.
-ClientThe name printed on the report.
-OutFile / -ExportJson / -OpenWhere to write the report, whether to add the JSON, and whether to open it.
-Gui / -SilentForces the options window (pre-filled by the other parameters), or forbids it — for a scheduled task. With neither, it opens only when the script is started with no parameter at all, on an interactive desktop.

With no parameter

A window to set up the health check.

Started with no parameter on a desktop, the script opens this window: the site, the account, what is read and where to write the report. Then the same window follows the run, phase by phase, and gives the verdict. Click around: it is the same window, in French as in the script.

Health check MECM - LB IT Cloud
LB IT CLOUD · HEALTH CHECK MECMLECTURE SEULE

Health check MECM

Lit le site Configuration Manager, ses serveurs, ses clients et le durcissement de chaque système de site, puis écrit un rapport HTML. Lecture seule : rien n'est modifié, rien n'est déployé.

SITE
Serveur de site (fournisseur SMS)
Code du site
Source
Code du site vide : découvert automatiquement. Automatique : l'AdminService, puis WMI s'il ne répond pas.
CE QUI EST LU
Messages d'état
Historique des composants
Journaux
La durée dépend surtout du nombre de systèmes de site et de clients : de une à quelques minutes sur un site moyen.
RAPPORT
Nom du client, imprimé sur le rapport
Langue
Dossier du rapport
C:\Users\admin\Documents\MECM-HealthCheck
LB IT Cloud · v1.72.2

The same thing, on a command line

Every choice in the window has its parameter. The line below follows your clicks: it is the one to put in a scheduled task or a remote session. The report is then written to the current folder, or wherever -OutFile says.

.\Invoke-MecmHealthCheck.ps1 -Open

The window never opens where it could hang an unattended run:

  • as soon as any parameter is passed: a command line is an explicit intent. -Gui opens it anyway, pre-filled by the other parameters;
  • under SYSTEM, nor in a session with no desktop;
  • with -Silent, for a scheduled task started with no other parameter.

The health check runs in a second PowerShell process, started by the window with these same parameters: the window stays responsive through the minutes of reading, and "Annuler" stops it outright. Started without administrator rights, it warns that the local machine's hardening will be partly unmeasured.

The code

The whole script.

Split into sections, each explained in one sentence. Everything is in plain text: no encoded block, no hidden download, no line that calls the Internet. You may run it in your organisation and at your clients': what is allowed is set out in its terms of use.

Invoke-MecmHealthCheck.ps1

v1.72.2 · 8,031 lines · 570 KB

What's new · version 1.72.2

What changes in this version.

1.72.2 makes its demonstration consistent, 1.72.1 gives the options window the site's design. Since 1.71.0: a window to start it, a validated remote run, reads fixed against a real production site, and a Security tab aligned with Misconfiguration Manager.

Starting it

  • An options window opens when the script is started with no parameter: site, account, what is read, report folder — then it follows the run live. -Gui forces it, -Silent forbids it.
  • Running it from a domain machine is validated. When the site answers without showing anything to the account — a missing role, or an account recreated while ConfigMgr keeps its old SID — the script stops and says what to check, instead of writing an empty report.
  • Starting it from PowerShell ISE works.

Reads fixed

  • Site system roles are counted: they stayed at zero on a real site.
  • Status messages are filtered on the period over the AdminService too, which used to return the oldest ones. A read that fails shows as "not read", no longer 0.
  • Client push is read where the site keeps it: automatic or not, domain controllers, accounts, NTLM fallback. The Network Access Account is actually read.
  • The deployment chart says when the site returns no counter, instead of announcing "no failure".

Security

  • A matrix of the 23 PREVENT measures of Misconfiguration Manager: for each one, the check that measures it and its status, or why it cannot be measured from the site.
  • Five new checks: the KB15599094 client push update (PREVENT-1), the F8 prompt on boot images (PREVENT-7), SQL Server Extended Protection (PREVENT-14), the domain's machine account quota (PREVENT-16), client cache permissions (PREVENT-23).
  • Shares are judged on their share AND NTFS permissions, compared with each product's baseline (ConfigMgr, WSUS, WDS): a write open to a broad group is critical.

Report

  • Drives: amber beyond 80 % used, red beyond 95 %, and bars that show the space used.
  • Clients: a "Healthy clients" tile — active, client health passing, recent policy and inventory.
  • The report wears the LB IT Cloud design, and the server card no longer overlaps.
  • 1.72.1 — the options window too: a plate on top, cut corners, narrow titles, monospaced labels, capital buttons.
  • 1.72.2 — the demonstration report gets its status messages and timeline back: replayed, a test set is dated from the day it was recorded.
  • The script's comments are in English and in French.

Demo report · fictitious data

Open in a tab

Did this page help?

Your answer is counted without identifying you: no account, no cookie, no comment — only which way you voted.