I have been seeing more and more issues with bad calendar items causing out of control mailbox database and transaction log growth. What I seen as a good process for attacking these issues is to use the following:
Recently, I have been trying to find a more proactive measure to identify these calendar items that tend to break when users just refuse to follow best practices.
I have combined PowerShell and CalCheck to look for bad items. Here is my latest version of the script. Please keep in mind that the formatting of this blog does not always work perfectly for scripts, and many of the lines that appear here are really a single line. You can download the latest version of this script here.
# This script is broken into three steps. In the first step, we identify users that have large calendar folders # In this step, we use get the databases first to try to minimize the memory requirements of processing all mailboxes # as PowerShell fails when you start getting into the tens of thousands of mailboxes.
$Date = Get-Date
Write-Host Start processing script at $Date # I always to keep track of how much time scripts take
$mbdb = Get-MailboxDatabase | Where {$_.name -ilike ‘*vpc*’} Write-Host $Null | Out-File List.txt foreach ($db in $mbdb){
Write-Host Processing $db
$Mailboxes = Get-Mailbox -database $db
foreach ($i in $Mailboxes){
$CalendarSize = (Get-Mailbox $i | Get-MailboxFolderStatistics -folderscope ‘calendar’).FolderandSubFolderSize
# Write-Host $i – Calendar size is $CalendarSize
$CalSplit = $CalendarSize -split ‘ ‘
$CalSize = $CalSplit[2]
$CalSize = $CalSize -replace “\(|\)|,| bytes”
$CalSize = [int]$CalSize
if ($CalSize -gt 100000000){
Get-Mailbox $i | Select Name,LegacyExchangeDN | FL | Out-File -append list.txt
}
}
}
$Date = Get-Date
Write-Host Completed identification of mailboxes that have large calendar folders at $Date
# In this step, we simply run CalCheck against all of the mailboxes that have calendar folders over 100MB as found in the first step. This requires version 2.0 or higher which supports the -l and –a arguments.
# It is vital that the account running this script have proper access to the individual mailboxes to scan them.
# The output will be a large number of log and csv files. I use the csv files for simpler processing.
# Note: Currently, CalCheck is not able to process more than around 100 mailboxes at a time. YMMV. You should also note that I pause the PowerShell script so that CalCheck can run.
Start-Process -FilePath c:\calcheck\calcheck.exe -ArgumentList “-a -l list.txt”
Write-Host “Once CalCheck has finished running, press any key to continue …”
$x = $host.UI.RawUI.ReadKey(“NoEcho,IncludeKeyDown”)
$Date = Get-Date
Write-Host Completed running CalCheck against mailboxes that have large calendar folders at $Date
# In this step, we create an output file for our results.
Write-Host $Null | Out-File Results.csv
$Header = “Subject,Organizer,Email,Modifications,Size”
$Header | Out-File Results.csv
$UserFiles = Dir C:\calcheck\calcheck_*.csv
foreach ($File in $UserFiles){
Write-Host ” “
Write-Host PROCESSING $file
Write-Host ” “
Copy $File CalItems.csv
(Get-Content calitems.csv) | where {$_ -notmatch ‘Processing*’} | Set-Content calitems.csv
$CalItems = Import-CSV calitems.csv
foreach ($item in $CalItems){
$Subject = $Item.Subject
$Size = $Item.Size
#This section is used to identify the organizer of the meeting and to put their info into first name, middle initial, last name format and also the same for their email address which I can use in other scripts to send automated email if I want. Your email address format may differ.
$Organizer = $Item.”Organizer Name”
$Organizer = $Organizer -split “_ “
$OrganizerFN = $Organizer[1]
$OrganizerLN = $Organizer[0]
$OrganizerFN1 = $OrganizerFN -split ” “
$OrganizerFN2 = $OrganizerFN1[0]
$OrganizerMI = $OrganizerFN1[1]
$Organizer = $OrganizerFN + ” ” + $OrganizerLN
if ($OrganizerMI){
$Email = $OrganizerFN2 + “.” + $OrganizerMI + “.” + $OrganizerLN + “@company.com”
}
if (!$OrganizerMI){
$Email = $OrganizerFN2 + “.” + $OrganizerLN + “@company.com”
}
if ($Modified = !$Null){
[int]$Modified = $Item.”Modified Instances”
if($Modified -ge “20″){
$Result = “$Subject,$Organizer,$Email,$Modified,$Size”
Write-Host $Result
$Result | Out-File -append Results.csv
}
}
}
Del CalItems.csv
}
$Date = Get-Date
Write-Host Completed script at $Date
What you will end up with is a csv file named results.csv that can then be loaded into Excel and sorted as needed to identify the items that may be causing the most pain.