Overview
Maintaining performance visibility across all Domain Controllers is critical in any Active Directory environment.
This script:
- Discovers all Domain Controllers automatically
- Creates a Performance Monitor Data Collector Set remotely
- Configures baseline counters
- Starts continuous circular logging
- Ensures required folder structure exists
- Executes safely across all DCs
It provides a standardized, automated method for collecting DC performance baselines.
Why Baseline Domain Controllers?
Without baseline metrics, it is impossible to determine:
- Whether high CPU is abnormal
- If LDAP traffic has increased unexpectedly
- If disk latency is degrading replication
- If memory pressure is affecting authentication
- Whether network throughput is bottlenecked
Baselining allows comparison between:
- Post-change performance
- Normal operation
- Incident periods
What the Script does
This script automates the deployment of a standardized performance baseline configuration across all Domain Controllers in the Active Directory environment. It dynamically discovers every domain controller, ensures a dedicated logging directory exists, remotely creates a Performance Monitor Data Collector Set using logman, and starts continuous circular logging. The collector captures critical system and Active Directory counters—including CPU usage, memory pressure, disk I/O, network throughput, and NTDS activity—at five-minute intervals, storing the data locally in a controlled, size-limited format. By executing these steps remotely via WMI, the script enforces consistent monitoring configuration across the infrastructure without requiring manual setup on each server, enabling long-term performance analysis, capacity planning, and incident investigation.
# Import AD module if not already loaded
Import-Module ActiveDirectory
# Get a list of Domain Controller hostnames
$DomainControllers = Get-ADDomainController -Filter * | Select-Object -ExpandProperty HostName
# Commands to run remotely (broken into steps for reliability)
$logmanCreate = 'logman create counter DC_Baseline_Monitoring -c "\Processor(_Total)\% Processor Time" "\Memory\Available MBytes" "\Memory\Pages/sec" "\LogicalDisk(_Total)\% Free Space" "\PhysicalDisk(_Total)\Disk Reads/sec" "\PhysicalDisk(_Total)\Disk Writes/sec" "\Network Interface(*)\Bytes Total/sec" "\NTDS\LDAP Searches/sec" "\NTDS\DS Directory Reads/sec" "\NTDS\DS Directory Writes/sec" -si 00:05:00 -o "C:\PerfLogs\DC_Baseline\DC_Baseline_Monitoring" -f bincirc -max 500 -v mmddhhmm -cnf 01:00:00'
$logmanStart = 'logman start DC_Baseline_Monitoring'
# Prepare the log directory creation as a PowerShell command
$prepareFolder = 'if (!(Test-Path C:\PerfLogs\DC_Baseline)) { New-Item -ItemType Directory -Path C:\PerfLogs\DC_Baseline }'
foreach ($dc in $DomainControllers) {
Write-Host "Configuring $dc..." -ForegroundColor Cyan
try {
# 1. Make sure the folder structure exists
$cmd = "powershell.exe -Command `$ErrorActionPreference = 'SilentlyContinue'; $prepareFolder"
$wmi = [WMIClass]"\\$dc\root\cimv2:Win32_Process"
$result = $wmi.Create($cmd)
if ($result.ReturnValue -eq 0) {
Write-Host "Log folder checked/created on $dc."
} else {
Write-Warning "Failed to create log folder on $dc. ReturnValue: $($result.ReturnValue)"
}
# 2. Create the Data Collector Set (safe to rerun; will fail if exists)
$result = $wmi.Create($logmanCreate)
if ($result.ReturnValue -eq 0) {
Write-Host "Data Collector Set created on $dc."
} else {
Write-Warning "Data Collector Set may already exist on $dc (ReturnValue: $($result.ReturnValue))."
}
# 3. Start the Data Collector Set
$result = $wmi.Create($logmanStart)
if ($result.ReturnValue -eq 0) {
Write-Host "Data Collector Set started on $dc."
} else {
Write-Warning "Data Collector Set may already be running on $dc (ReturnValue: $($result.ReturnValue))."
}
} catch {
Write-Error "Error contacting $dc: $_"
}
}

