Skip to content

Instantly share code, notes, and snippets.

@bill-long
Last active February 16, 2024 19:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bill-long/8a4f6eb44dd88db13c67a00c9903f27c to your computer and use it in GitHub Desktop.
Save bill-long/8a4f6eb44dd88db13c67a00c9903f27c to your computer and use it in GitHub Desktop.
[CmdletBinding()]
param (
[Parameter(Mandatory = $false)]
[int]$MaxRetries = 20,
[Parameter(Mandatory = $false)]
[string]$LogFilePath = "$PSScriptRoot\GetAllPFStatistics.log"
)
function WriteHostAndLog($message) {
Write-Host $message
Add-Content -Path $LogFilePath -Value $message
}
function WriteLog($message) {
Add-Content -Path $LogFilePath -Value $message
}
function GetResidentFoldersWithRetry($PFMailboxResult) {
while ($true) {
try {
WriteHostAndLog "$(Get-Date) Getting hierarchy for $($PFMailboxResult.Mailbox.Name)"
$folders = @(Get-PublicFolder -Mailbox $PFMailboxResult.Mailbox.Name -ResidentFolders -Recurse -ResultSize Unlimited -ErrorAction Stop)
# Skip the root folder
if ($folders.Count -gt 1) {
$folders = $folders[1..$($folders.Count - 1)]
} else {
$folders = @()
}
WriteHostAndLog "$(Get-Date) Found $($folders.Count) public folders in mailbox $($PFMailboxResult.Mailbox.Name)"
$PFMailboxResult.Folders = $folders
return
} catch {
WriteHostAndLog "$(Get-Date) Error getting hierarchy: $($_.Exception.Message)"
$_ | Format-List * -Force | Out-String | ForEach-Object { WriteLog $_ }
[void]$PFMailboxResult.Errors.Add([PSCustomObject]@{
Time = (Get-Date)
Stage = "Hierarchy"
Folder = $null
Error = $_
})
if ($errors.Count -ge $MaxRetries) {
WriteHostAndLog "$(Get-Date) Max retries reached, skipping mailbox $($PFMailboxResult.Mailbox.Name)"
break
} else {
WriteHostAndLog "$(Get-Date) Retrying in 5 seconds..."
Start-Sleep -Seconds 5
continue
}
}
}
}
function GetPFMailboxStatisticsWithRetry($PFMailboxResult) {
WriteHostAndLog "$(Get-Date) Getting statistics for folders in mailbox $($PFMailboxResult.Mailbox.Name)"
$mailboxRetryCount = 0
while ($PFMailboxResult.StatisticsProgressIndex -lt $PFMailboxResult.Folders.Count) {
if ($mailboxRetryCount -ge $MaxRetries) {
WriteHostAndLog "$(Get-Date) Max retries reached. Moving on to the next mailbox."
break
}
$folder = $PFMailboxResult.Folders[$PFMailboxResult.StatisticsProgressIndex]
if ($folder.Identity.ToString() -eq "\") {
$PFMailboxResult.StatisticsProgressIndex++
continue
}
Write-Progress -Id 2 -ParentId 1 -Activity "Getting statistics" -Status "$($folder.Identity)" -PercentComplete ($PFMailboxResult.StatisticsProgressIndex / $PFMailboxResult.Folders.Count * 100)
$folderRetryCount = 0
while ($true) {
try {
$stats = $folder | Get-PublicFolderStatistics -ErrorAction Stop
[void]$PFMailboxResult.Statistics.Add($stats)
$PFMailboxResult.StatisticsProgressIndex++
break
} catch {
WriteHostAndLog "$(Get-Date) Error getting statistics on folder $($folder.Identity): $($_.Exception.Message)"
if ($_.ToString().Contains("ManagementObjectNotFoundException")) {
WriteHostAndLog "$(Get-Date) Folder appears to be deleted. Skipping..."
$PFMailboxResult.StatisticsProgressIndex++
break
}
$_ | Format-List * -Force | Out-String | ForEach-Object { WriteLog $_ }
$folderRetryCount++
[void]$PFMailboxResult.Errors.Add([PSCustomObject]@{
Time = (Get-Date)
Stage = "Statistics"
Folder = $folder.Identity
Error = $_
})
if ($folderRetryCount -ge $MaxRetries) {
$mailboxRetryCount = $folderRetryCount
break
} else {
WriteHostAndLog "$(Get-Date) Retrying in 5 seconds..."
Start-Sleep -Seconds 5
}
}
}
}
Write-Progress -Id 2 -ParentId 1 -Activity "Getting statistics" -Completed
}
function GetAndSaveResults($PassName, $ExistingResults) {
for ($i = 0; $i -lt $ExistingResults.Count; $i++) {
$pfMailboxResult = $ExistingResults[$i]
if ($null -ne $pfMailboxResult.Folders) {
continue
}
Write-Progress -Id 1 -Activity "Getting hierarchy" -Status "Mailbox: $($pfMailboxResult.Mailbox.Name)" -PercentComplete ($i / $ExistingResults.Count * 100)
$newResult = GetResidentFoldersWithRetry -PFMailboxResult $pfMailboxResult
if ($null -ne $newResult.Folders) {
$pfMailboxResult.Folders = $newResult.Folders
}
}
Write-Progress -Id 1 -Activity "Getting hierarchy" -Completed
for ($i = 0; $i -lt $ExistingResults.Count; $i++) {
$pfMailboxResult = $ExistingResults[$i]
if ($null -eq $pfMailboxResult.Folders -or $pfMailboxResult.StatisticsProgressIndex -ge $pfMailboxResult.Folders.Count) {
continue
}
Write-Progress -Id 1 -Activity "Getting statistics" -Status "Mailbox: $($pfMailboxResult.Mailbox.Name)" -PercentComplete ($i / $ExistingResults.Count * 100)
# This is null if we had to skip it due to too many retries on the hierarchy
if ($null -ne $pfMailboxResult.Folders) {
GetPFMailboxStatisticsWithRetry -pfMailboxResult $pfMailboxResult
}
}
Write-Progress -Id 1 -Activity "Getting statistics" -Completed
WriteHostAndLog "$(Get-Date) Results after $PassName pass:"
$pfMailboxResults | ForEach-Object {
[PSCustomObject]@{
Mailbox = $($_.Mailbox.Name)
ErrorCount = $($_.Errors.Count)
HierarchyCount = $(if ($null -ne $_.Folders) { $_.Folders.Count } else { $null })
StatisticsCount = $($_.Statistics.Count)
}
} | Format-Table -AutoSize | Out-String | ForEach-Object { WriteHostAndLog $_ }
WriteHostAndLog "$(Get-Date) Writing $PassName pass results to CSV..."
$pfMailboxResults.Statistics | Select-Object @{Name = "FolderPath"; Expression = { $_.FolderPath -join "\" } }, ItemCount, @{Name = "TotalItemSizeMB"; Expression = { [math]::Round(($_.TotalItemSize.ToString().Split("(")[1].Split(" ")[0].Replace(",", "") / 1MB), 2) } } | Export-Csv $PSScriptRoot\$($PassName)PassResults.csv -NoTypeInformation -Encoding utf8
}
WriteHostAndLog "$(Get-Date) Getting public folder mailboxes..."
$pfMailboxes = Get-Mailbox -PublicFolder
WriteHostAndLog "$(Get-Date) Found $($pfMailboxes.Count) public folder mailboxes."
$pfMailboxResults = [System.Collections.ArrayList]::new()
foreach ($mailbox in $pfMailboxes) {
[void]$pfMailboxResults.Add([PSCustomObject]@{
Mailbox = $mailbox
Folders = $null
Statistics = [System.Collections.ArrayList]::new()
StatisticsProgressIndex = 0
Errors = [System.Collections.ArrayList]::new()
})
}
GetAndSaveResults "First" $pfMailboxResults
$skippedHiearchy = $pfMailboxResults | Where-Object { $null -eq $_.Folders }
$skippedStatistics = $pfMailboxResults | Where-Object { $_.Statistics.Count -lt $_.Folders.Count }
if ($skippedHiearchy.Count -eq 0 -and $skippedStatistics.Count -eq 0) {
WriteHostAndLog "$(Get-Date) No skipped items. Done."
return
}
WriteHostAndLog "$(Get-Date) Skipped mailboxes due to too many retries on hierarchy: $($skippedHiearchy.Count)"
WriteHostAndLog "$(Get-Date) Skipped mailboxes due to too many retries on statistics: $($skippedStatistics.Count)"
WriteHostAndLog "$(Get-Date) Retrying skipped items..."
GetAndSaveResults "Second" $pfMailboxResults
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment