<
.SYNOPSIS
Extracts and processes Disk I/O activity from a log file and exports the top entries to CSV.
.DESCRIPTION
- Reads the DiskIoActivityTracker log file.
- Filters lines that start with "Timestamp".
- Extracts relevant information using regex.
- Sorts by TransferSizeMB in descending order and selects the top results.
- Exports the results to a user-specified CSV file.
.PARAMETER CsvFilePath
Full path to the output CSV file where results will be stored.
.PARAMETER Top
Maximum number of files shown in the table and CSV.
.EXAMPLE
.\DiskIoParser.ps1 -CsvFilePath "C:\Output\Top50Results.csv"
.AUTHOR
Chris Twiest and Guy Leech
.NOTES
Modification History
2025/03/05 Chris Twiest Initial release
2025/03/14 Guy Leech Optimised. Added -raw and -daysback
[CmdletBinding(DefaultParameterSetName='csv')]
param (
[Parameter(Mandatory = $true, ParameterSetName = 'csv' , HelpMessage = "Show amount of files")]
[int]$Top,
[Parameter(Mandatory = $true, ParameterSetName = 'csv' , HelpMessage = "Enter the full path to the CSV output file")]
[string]$CsvFilePath ,
[Parameter(Mandatory = $false, ParameterSetName = 'raw')]
[switch]$raw
)
try
{
[int]$outputWidth = 400
if( ( $PSWindow = (Get-Host).UI.RawUI ) -and ( $WideDimensions = $PSWindow.BufferSize ) )
{
$WideDimensions.Width = $outputWidth
$PSWindow.BufferSize = $WideDimensions
}
}
catch
{
}
$LogDirectory = Join-Path -Path ([Environment]::GetFolderPath( [Environment+SpecialFolder]::CommonApplicationData )) -ChildPath 'ControlUp\DiskMonitor'
$LogFilePattern = "ActivitiesSummary*"
$TodayStart = (Get-Date).Date
$TodayEnd = $TodayStart.AddDays(1).AddSeconds(-1)
$daysBack = 7
$CutoffDate = (Get-Date).AddDays( -$daysBack)
$LogFiles = Get-ChildItem -Path $LogDirectory -Filter $LogFilePattern -File
$TodaysLogFiles = $LogFiles | Where-Object { $_.LastWriteTime -ge $TodayStart -and $_.LastWriteTime -le $TodayEnd } | Sort-Object LastWriteTime -Descending
Write-Verbose -Message "Start date is $($CutoffDate.ToString('G'))"
$OldLogFiles = $LogFiles | Where-Object { $_.CreationTime -lt $CutoffDate }
if ($OldLogFiles) {
Write-Output "INFO: Deleting $(($OldLogFiles).Count) log file(s) older than 7 days..."
$OldLogFiles | ForEach-Object {
Remove-Item $_.FullName -Force -ErrorAction SilentlyContinue
Write-Output "Deleted: $($_.FullName)"
}
}
if (-Not $TodaysLogFiles) {
Write-Error "ERROR: No log files created today ($TodayStart - $TodayEnd) found in $LogDirectory"
exit 1
}
$LogFilePath = $TodaysLogFiles.FullName
$systemDrive = $env:SystemDrive
$drive = Get-PSDrive -Name ($systemDrive -replace ':', '')
$freeSpaceGB = [math]::Round($drive.Free / 1GB, 2)
try {
Write-Output "Reading log file: $LogFilePath"
$Results = @( [IO.File]::ReadLines( $LogFilePath ) | Where-Object { $_ -match 'Timestamp:(.*?), Interval:(\d+), Process Id:(\d+), ProcessName:(.*?), UserName:(.*?), FileName:(.*?), TransferSize \(MB\):([\d,\.]+)' } | ForEach-Object {
[PSCustomObject]@{
Timestamp = $( if( $timestamp = $matches[1] -as [datetime] ) { $timestamp } else { [datetime]$matches[1] })
Interval = [int]$matches[2]
ProcessId = [int]$matches[3]
ProcessName = $matches[4].Trim()
UserName = $matches[5].Trim()
FileName = $matches[6].Trim()
TransferSizeMB = [math]::Round(($matches[7] -replace ",", ".") -as [double], 2)
FreespaceGB = $freeSpaceGB
}
})
if( $Results.Count -eq 0 ) {
Throw "No results read from $LogFilePath"
}
if( $raw ) {
$Results
}
else {
$TopResults = $Results | Sort-Object -Property TransferSizeMB -Descending | Select-Object -First $Top
$TopResults | Where-Object {$_.Filename -notlike "*pagefile.sys"} | Select-Object Timestamp, ProcessName, UserName, TransferSizeMB, FileName | Format-Table
$TopResults | Where-Object {$_.Filename -notlike "*pagefile.sys"} | Export-Csv -Path $CsvFilePath -NoTypeInformation -Force
Write-Output "Top $Top results exported to: $CsvFilePath"
}
} catch {
Write-Error "ERROR: An error occurred while processing the log file: $_"
exit 1
}