If you spend time building SCOM performance reports, you’ll love these two new additions to the SCOMHelper PowerShell module embedded in the SCOMHelper management pack. They make it simple to discover which performance counters are collected for a server and then retrieve the historical data directly from the SCOM Data Warehouse. This is perfect for creating your own SCOM performance report PowerShell workflows, dashboards, and capacity planning analyses.
What's New
Typical use cases
- Build SCOM performance report PowerShell workflows for CPU, memory, disk, IIS, SQL, and more.
- Trend disk free space by drive over 30/90/180 days to anticipate capacity needs.
- Establish baselines and compare to recent behavior (performance drift detection).
- Troubleshoot “is SCOM collecting this data?” questions by mapping counters to their rules and sample ranges.
- Generate CSVs for Excel/Power BI charts and scheduled reporting.
Supported versions and prerequisites
- SCOM: 2016, 2019, 2022.
(Not tested on 2025 yet, but expected to work as the components used rarely change.) - Permissions: Read access to the SCOM Data Warehouse (OperationsManagerDW).
- Connectivity: Network access to your DW SQL instance. Active connection to a SCOM Management Group.
- Install: The preferred method is installing the SCOMHelper management pack manually (the SCOMHelper PowerShell module is embedded). Alternative module install from the PowerShell Gallery is possible, but the MP install is preferred. See: https://monitoringguys.com/2019/11/12/scomhelper/
How the two cmdlets fit together
- Use Get-SCOMDWPerformanceDataSignature to discover exactly which counters SCOM collects for a server (including related instances like disks, services, and apps) and to identify the RuleId(s).
- Pipe those signatures into Get-SCOMDWPerformanceData to pull hourly or daily aggregated data for specific counters and time ranges.
Quick start
Note: Ensure you’ve imported the OperationsManager and SCOMHelper PowerShell modules and are connected to your Management Group before running the examples.
Example 1: Discover CPU counters on SQL21 and pull 30-day daily trends
# Discover the % Processor Time counter (_Total) for SQL21
$cpuSig = Get-SCOMDWPerformanceDataSignature -ComputerName SQL21.contoso.com | `
Where-Object { $_.ObjectName -eq "Processor Information" -and $_.CounterName -eq "% Processor Time" -and $_.InstanceName -eq "_Total" }
# Get 30 days of daily CPU data
$cpu30 = $cpuSig | Get-SCOMDWPerformanceData -StartDate (Get-Date).AddDays(-30) -AggregationType Daily
# Save for charting (Excel/Power BI)
$cpu30 | Select-Object DateTime, AverageValue, MinValue, MaxValue, SampleCount `
| Sort-Object DateTime `
| Export-Csv "C:\Reports\SQL21-CPU-30d.csv" -NoTypeInformation

Example 2: 90-day disk free space trend for Web21, by drive (daily aggregation)
# Find the % Free Space logical disk counters for Web21
$diskSigs = Get-SCOMDWPerformanceDataSignature -ComputerName Web21.contoso.com `
| Where-Object { $_.ObjectName -eq "LogicalDisk" -and $_.CounterName -eq "% Free Space" }
# Retrieve 90 days of daily data for all disk instances
$diskData = $diskSigs | Get-SCOMDWPerformanceData -StartDate (Get-Date).AddDays(-90) -AggregationType Daily
# Export one CSV per drive for easy charting
$diskData | Group-Object InstanceName | ForEach-Object {
$path = "C:\Reports\Web21-$($_.Name.Replace(':',''))-FreeSpace-90d.csv"
Write-Host $Path -ForegroundColor Cyan
$_.Group | Select-Object DateTime, AverageValue, MinValue, MaxValue, SampleCount, InstanceName | Sort-Object DateTime | Export-Csv -Path $path -NoTypeInformation
}

Example 4: Baseline vs recent CPU on AD01 to detect drift
# Baseline: 90–30 days ago (daily)
$cpuSigAd = Get-SCOMDWPerformanceDataSignature -ComputerName AD01.contoso.com `
| Where-Object { $_.ObjectName -eq "Processor" -and $_.CounterName -eq "% Processor Time" -and $_.InstanceName -eq "_Total" }
$baseline = $cpuSigAd | Get-SCOMDWPerformanceData -StartDate (Get-Date).AddDays(-90) -EndDate (Get-Date).AddDays(-30) -AggregationType Daily
# Recent: last 7 days (daily)
$recent = $cpuSigAd | Get-SCOMDWPerformanceData -StartDate (Get-Date).AddDays(-14) -AggregationType Daily
$baselineAvg = ($baseline | Measure-Object -Property AverageValue -Average).Average
$recentAvg = ($recent | Measure-Object -Property AverageValue -Average).Average
$percentChange = [math]::Round((($recentAvg - $baselineAvg) / $baselineAvg) * 100, 2)
Write-Host "AD01 CPU baseline (90-30 days ago):`t$([math]::Round($baselineAvg,2))%" -F Yellow
Write-Host "AD01 CPU recent (last 7 days):`t`t$([math]::Round($recentAvg,2))%" -F Yellow
Write-Host "Change vs baseline:`t`t`t$percentChange%" -F Yellow

Example 5: Pull “everything collected” for a computer (use sparingly)
# Returns all counters across related objects for the last 14 days (hourly)
# This is a tremendous amount of data
$allPerf = Get-SCOMDWPerformanceData -ComputerName SQL21.contoso.com -StartDate (Get-Date).AddDays(-14) -AggregationType Hourly
# See which counters are most active
$top = $allPerf | Group-Object ObjectName, CounterName | Sort-Object Count -Descending | Select-Object -First 10
$top | Format-Table Name, Count -AutoSize
# Export all data if needed
$allPerf | Export-Csv "C:\Reports\SQL21-AllPerf-14d-Hourly.csv" -NoTypeInformation
# Tip: For long periods (90–180 days), prefer -AggregationType Daily to keep the dataset manageable.
Example 6: Create a monthly SCOM performance report PowerShell CSV from a simple list
# Report last 30 days of daily disk free space for multiple servers
$servers = @("SQL21.contoso.com","Web21.contoso.com","AD01.contoso.com")
$results = foreach ($s in $servers) {
try {
$sig = Get-SCOMDWPerformanceDataSignature -ComputerName $s `
| Where-Object { $_.ObjectName -eq "LogicalDisk" -and $_.CounterName -eq "% Free Space" }
$data = $sig | Get-SCOMDWPerformanceData -StartDate (Get-Date).AddDays(-30) -AggregationType Daily -ErrorAction Stop
$data | ForEach-Object {
$_ | Select-Object @{n='ComputerName';e={$s}}, ObjectName, CounterName, InstanceName, DateTime, AverageValue, MinValue, MaxValue, SampleCount
}
}
catch {
Write-Warning "Failed to process $($s): $($_.Exception.Message)"
}
}
$results | Export-Csv "C:\Reports\Monthly-DiskFree-Report.csv" -NoTypeInformation
What each cmdlet returns (at a glance)
- Get-SCOMDWPerformanceDataSignature returns properties like ManagedEntityGuid, FullName, ObjectName, CounterName, InstanceName, NumSamples, OldestSample, NewestSample, RuleName, RuleDisplayName, RuleId, ManagementPackName, ManagementPackId.
- Get-SCOMDWPerformanceData returns properties like DateTime, AverageValue, MinValue, MaxValue, SampleCount, MonitoringObjectId, RuleId, CounterName, ObjectName, InstanceName.
Performance and best practices
- Prefer daily aggregation for long time frames (90–180 days). Use hourly when you need resolution for recent periods.
- Start with scoped signatures (RuleId/ObjectName/CounterName) to reduce query size and speed results.
- Adjust -QueryTimeout if your environment has very large datasets.
- When producing executive reports, export CSV and chart in Excel or Power BI for polished visuals.
Troubleshooting tips
- Ensure you have an active SCOM PowerShell session against the correct Management Group.
- Verify you have read access to OperationsManagerDW.
- If auto-discovery of the DW server fails, specify -DataWarehouseServerName and -DataWarehouseDatabaseName explicitly.
- If you’re not seeing expected counters, run the signature function first to confirm RuleId and sample windows.
Why this matters
These cmdlets make it easy to build repeatable SCOM performance report PowerShell workflows. You can answer “what do we collect?” and “how has it trended?” in minutes, then export to CSV for charts, dashboards, and capacity planning—without writing custom SQL or wading through the SCOM console’s reporting UI.
Where to get SCOMHelper
SCOMHelper is packaged as a management pack (preferred install) and also available as a PowerShell module. Installation details and the full module overview are here: