This was just a very quick script to tell me the top 10 processes utilizing the disk, it was more of a quick requirement I needed so I thought I’d put it on my blog just in case it helps anyone else.
Script : DiskMonitor.ps1
# Define a loop to monitor disk I/O continuously
while ($true) {
try {
# Get the current time for logging
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
# Get disk I/O per process
Write-Host "Querying disk I/O statistics at $timestamp..."
$diskStats = Get-Counter -Counter "\Process(*)\IO Data Bytes/sec" `
-SampleInterval 5 -MaxSamples 1 -ErrorAction Stop
# Check if the data returned is valid
if ($diskStats.CounterSamples.Count -eq 0) {
Write-Host "No data returned from performance counters."
Start-Sleep -Seconds 10
continue
}
# Process valid data
$diskData = $diskStats.CounterSamples | Where-Object {
$_.InstanceName -ne "_Total" -and $_.InstanceName -ne "Idle"
} | Select-Object InstanceName, CookedValue | Sort-Object CookedValue -Descending
if ($diskData.Count -eq 0) {
Write-Host "No valid disk I/O data found."
Start-Sleep -Seconds 10
continue
}
# Get the top 10 processes using the most disk I/O
$topProcesses = $diskData | Select-Object -First 10
# Optional: Calculate total disk I/O
$totalDiskIO = $diskData | Measure-Object -Property CookedValue -Sum
$totalDiskIOValue = [math]::Round($totalDiskIO.Sum / 1KB, 2) # Convert to KB
# Output the results
Write-Host "Timestamp: $timestamp"
Write-Host "Total Disk I/O: ${totalDiskIOValue} KB/sec"
Write-Host "Top 10 Processes by Disk I/O (Bytes/sec):"
# Format results into a table
$formattedResults = $topProcesses | ForEach-Object {
[PSCustomObject]@{
ProcessName = $_.InstanceName
DiskIOBytesPerSec = [math]::Round($_.CookedValue / 1KB, 2) # Convert to KB
}
}
$formattedResults | Format-Table -AutoSize -Property ProcessName, DiskIOBytesPerSec
Write-Host "-------------------------------------"
}
catch {
Write-Host "An error occurred: $_" -ForegroundColor Red
}
# Wait before the next iteration
Start-Sleep -Seconds 10
}