I have found the below powershell script that pulls highitems from exchange 2010. I would like to modify the script to exclude users who are part of a specific OU. I am also looking to include archive mailbox sizes, if possible. I know this script was written
t work with several versions of exchange, I am open to creating a new script that can get the necessary info (folder path, item count, and database), but I dont know how to do it for a specific ou. Any help is greatly appreciated. Thank you so much.
#################################################################################
#
# The sample scripts are not supported under any Microsoft standard support
# program or service. The sample scripts are provided AS IS without warranty
# of any kind. Microsoft further disclaims all implied warranties including, without
# limitation, any implied warranties of merchantability or of fitness for a particular
# purpose. The entire risk arising out of the use or performance of the sample scripts
# and documentation remains with you. In no event shall Microsoft, its authors, or
# anyone else involved in the creation, production, or delivery of the scripts be liable
# for any damages whatsoever (including, without limitation, damages for loss of business
# profits, business interruption, loss of business information, or other pecuniary loss)
# arising out of the use of or inability to use the sample scripts or documentation,
# even if Microsoft has been advised of the possibility of such damages
#
#################################################################################
param(
[bool] $CriticalFoldersOnly = $true,
[string] $Database = "",
[string] $DomainController = "",
[bool] $FormatList = $false,
[int32] $ItemCount = -1,
[string] $OutputFile = "",
[string] $ResultSize = "unlimited",
[string] $Server = "")
#Script Parameters:
#-CriticalFoldersOnly: Only checks Calendar, Contacts, Inbox, and Sent Items. The default value is $true.
#-Database: Specifies the target Database. Overrides the -Server option if set.
#-DomainController: Specifies the default Domain Controller to use for mailbox and folder tests.
#-FormatList: Outputs to the screen in list format. The default is table format.
#-ItemCount: Ignores the max limits, and finds folders with the specified item count.
#-OutputFile: Specifies the output file. Should be in .CSV format.
#-ResultSize: Specifies the maximum number of mailboxes to check. The default value is unlimited.
#-Server: Specifies the target Exchange server.
# Function used to check the individual item count of folders within a given mailbox
function checkFolderItems
{
param(
$mbx,
[ref]$fldrArray,
[ref]$mbxFailed)
#Set item limit to search for
[int32] $maxItems = 5000
if ($mbx.ExchangeVersion -eq "2000")
{
$maxItems = $2kmax
}
elseif ($mbx.ExchangeVersion -eq "2003")
{
$maxItems = $2k3max
}
elseif ($mbx.ExchangeVersion -eq "2007")
{
$maxItems = $2k7max
}
elseif ($mbx.ExchangeVersion -eq "2010")
{
$maxItems = $2k10max
}
#Create the base of our Get-MailboxFolderStatistics command
$getFoldersString = "Get-MailboxFolderStatistics -Identity `"$($mbx.Identity)`""
#-ErrorAction SilentlyContinue"
#Add the domain controller if specified
if ($DomainController -ne "")
{
$getFoldersString += " -DomainController $DomainController"
}
#Add the filter portion of the command
if ($CriticalFoldersOnly -eq $true)
{
$getFoldersString += " | Where {(`$_.Name -like 'Calendar' -or `$_.Name -like 'Contacts' -or `$_.Name -like 'Inbox' -or `$_.Name -like 'Sent Items') -and `$_.ItemsInFolder -ge $maxItems}"
}
else
{
$getFoldersString += " | Where {`$_.ItemsInFolder -ge $maxItems}"
}
#Get the current error count so we can report errors after checking folders
$errorCountBefore = $error.Count
#Actually run our command and process all folders over the item limit
Invoke-Expression -Command $getFoldersString | ForEach-Object{
$folder = New-Object PSObject
$folder | Add-Member NoteProperty User $mbx.Alias -Force
$folder | Add-Member NoteProperty Folder $_.FolderPath -Force
$folder | Add-Member NoteProperty ItemCount $_.ItemsInFolder -Force
$folder | Add-Member NoteProperty Database $mbx.Database -Force
$folder | Add-Member NoteProperty Version $mbx.ExchangeVersion -Force
if ($fldrArray.Value[0] -ne "")
{
$fldrArray.Value += @($folder)
}
else
{
$fldrArray.Value = @($folder)
}
}
#Now check the current error count. Report an error if it is larger than when we started
if ($error.Count -gt $errorCountBefore)
{
Write-Host -ForeGroundColor red "ERROR: Unable to process mailbox '$($mbx.Alias)'."
$mbxFailed.Value++
}
}
# Function that checks whether the target server or database is inaccessible.
# This prevents us from timing out on each inaccessible mailbox.
# Note, this does not work against 2000-2003 mailboxes.
# Returns $true if accessible, and $false is not.
function checkAccessibility
{
param(
[ref]$badServers,
[ref]$badDBs,
[ref]$goodServers,
[ref]$goodDBs,
[ref]$mbxFailed,
$mbx)
#Check database and server accessibility. If mailbox is not on Exchange 2007+, or the server or database are already bad, fail.
if ($mbx.ExchangeVersion -ge 2007 -and !($badDBs.Value -Contains $mbx.Database) -and !($badServers.Value -Contains $mbx.ServerName))
{
#Check if mailbox is on a higher version of Exchange than this shell
if ($mbx.ExchangeVersion -ge 2010 -and (Get-Command "Microsoft.Exchange.PowerShell.Configuration.dll").FileVersionInfo.FileVersion -lt "14")
{
Write-Host -ForeGroundColor red "ERROR: Server '$($mbx.ServerName)' is running a higher version of Exchange than this machine. Skipping all mailboxes on this server."
$badServers.Value += $mbx.ServerName
$mbxFailed.Value++
return $false
}
#Check if database or server is already marked as good.
$serverGood = $false
$dbGood = $false
if ($goodServers.Value -Contains $mbx.ServerName)
{
$serverGood = $true
}
if ($goodDBs.Value -Contains $mbx.Database)
{
$dbGood = $true
}
#Either the server or database have not been marked as good. Proceed with connectivity test.
if (!$serverGood -or !$dbGood)
{
$failed = $false
$testMAPIString = "Test-MAPIConnectivity -Database '$($mbx.Database)' -PerConnectionTimeout 10 -ErrorAction SilentlyContinue"
if ($DomainController -ne "")
{
$testMAPIString += " -DomainController $DomainController"
}
$testMAPI = Invoke-Expression -Command $testMAPIString
#Check if the server is accessible
if (!$serverGood -and $testMAPI.Error -like "Microsoft Exchange Information Store service is not running.")
{
Write-Host -ForeGroundColor red "ERROR: Server '$($mbx.ServerName)' is inaccessible. Skipping all mailboxes on this server."
$badServers.Value += $mbx.ServerName
$failed = $true
}
else
{
$goodServers.Value += $mbx.ServerName
}
#Check if the database is accessible
if (!$dbGood -and $testMAPI.Result -like "*Failure*" -and $testMAPI.Error -notlike "Microsoft Exchange Information Store service is not running.")
{
Write-Host -ForeGroundColor red "ERROR: Database '$($mbx.Database)' is inaccessible. Skipping all mailboxes on this database."
$badDBs.Value += $mbx.Database
$failed = $true
}
else
{
$goodDBs.Value += $mbx.Database
}
#Check if we failed
if ($failed)
{
$mbxFailed.Value++
return $false
}
else
{
return $true
}
}
else
{
#The server and database are both in the good list. Proceed with checking mailbox
return $true
}
}
elseif ($mbx.ExchangeVersion -lt 2007)
{
#Do nothing and proceed to checking mailbox
return $true
}
else
{
#The server or database is in the bad list. Skip this mailbox
$mbxFailed.Value++
return $false
}
}
# Function that writes output to the screen, and writes to the output file if specified
function writeOutput
{
param(
[ref]$fldrArray)
[int32] $maxItems = 5000
if ($fldrArray.Value[0].Version -eq "2000")
{
$maxItems = $2kmax
}
elseif ($fldrArray.Value[0].Version -eq "2003")
{
$maxItems = $2k3max
}
elseif ($fldrArray.Value[0].Version -eq "2007")
{
$maxItems = $2k7max
}
elseif ($fldrArray.Value[0].Version -eq "2010")
{
$maxItems = $2k10max
}
#Write output to screen
$screenOutput = @()
Write-Host ""
Write-Host -ForeGroundColor green "Exchange $($fldrArray.Value[0].Version) Folders With $($maxItems) or More Items:"
for ($i = 0; $i -lt $fldrArray.Value.Length; $i++)
{
$screenOutput += $($fldrArray.Value[$i])
#Write output to file
if ($usingOutput -eq $true)
{
$currentLine = "$($fldrArray.Value[$i].User)`t$($fldrArray.Value[$i].Folder)`t$($fldrArray.Value[$i].ItemCount)`t$($fldrArray.Value[$i].Database)`t$($fldrArray.Value[$i].Version)"
$currentLine | Out-File -Append -NoClobber $OutputFile
}
}
#Check whether we should output in list or table format
if ($FormatList)
{
Write-Output $screenOutput | fl User, Folder, ItemCount, Database
}
else
{
Write-Output $screenOutput | ft User, Folder, ItemCount, Database -Autosize
}
#Add the folders from this pass to the master output array
$outputArray += $screenOutput
$screenOutput = $null
}
#Function that parses the ExchangeVersion property on a mailbox
function getExchangeVersion
{
param(
[ref]$mbx)
[double] $mbxVer = 0
#Check whether ExchangeVersion is set properly on the mailbox
if ($mbx.Value.ExchangeVersion.ExchangeBuild.Major -lt 6 -or $mbx.Value.ExchangeVersion.ExchangeBuild.Major -gt 20)
{
#ExchangeVersion is not set properly. Defaulting to Exchange 2010
$mbxVer = 14
}
else
{
$mbxVer = $mbx.Value.ExchangeVersion.ExchangeBuild.Major + ($mbx.Value.ExchangeVersion.ExchangeBuild.Minor/10)
}
#Convert the version to a string
#The mailbox is 2010
if ($mbxVer -ge 14)
{
$mbxVer = "2010"
}
#The mailbox is 2007
elseif ($mbxVer -ge 8 -and $mbxVer -le 8.5)
{
$mbxVer = "2007"
}
#The mailbox is 2003
elseif ($mbxVer -eq 6.5)
{
$mbxVer = "2003"
}
#The mailbox is 2000
elseif ($mbxVer -ge 6 -and $mbxVer -lt 6.5)
{
$mbxVer = "2000"
}
#We didn't find the version. Default to 2010
else
{
$mbxVer = "2010"
}
return $mbxVer
}
# Function that returns true if the incoming argument is a help request
function IsHelpRequest
{
param($argument)
return ($argument -eq "-?" -or $argument -eq "-help");
}
# Function that displays the help related to this script following
# the same format provided by get-help or <cmdletcall> -?
function Usage
{
@"
NAME:
`tHighItemFolders.ps1
SYNOPSIS:
`tFinds users who have folders with more than the recommended
`titem count. The item count that is searched for is different for
`teach Exchange version:
`t`tExchange 2000: 5000 Items
`t`tExchange 2003: 5000 Items
`t`tExchange 2007: 20,000 Items
`t`tExchange 2010: 100,000 Items
SYNTAX:
`tHighItemFolders.ps1
`t`t[-CriticalFoldersOnly <BooleanValue>]
`t`t[-Database <DatabaseIdParameter>]
`t`t[-DomainController <StringValue>]
`t`t[-FormatList <BooleanValue>]
`t`t[-ItemCount <IntegerValue>]
`t`t[-OutputFile <OutputFileName>]
`t`t[-ResultSize <StringValue>]
`t`t[-Server <ServerIdParameter>]
PARAMETERS:
`t-CriticalFoldersOnly
`t`tSpecifies whether to check only Critical Folders, which
`t`tare Calendar, Contacts, Inbox, and Sent Items. Should be
`t`tinput as either `$true or `$false. If omitted, the default
`t`tvalue is $true.
`t-Database
`t`tSpecifies the target database.
`t`tOverrides the -Server switch if used.
`t-DomainController
`t`tSpecifies the Domain Controller to use for all mailbox
`t`tand folder tests. If omitted, the default value is `$null.
`t-FormatList
`t`tWrites output to the screen in list format instead of
`t`ttable format. Should be input as either `$true or `$false.
`t`tIf omitted, the default value is `$false.
`t-ItemCount
`t`tIgnores the max limits, and finds folders with the
`t`tspecified item count.
`t-OutputFile
`t`tSpecifies the output file. Should be in .CSV format.
`t-ResultSize
`t`tSpecifies the maximum number of mailboxes to be checked.
`t`tCan be specified either as a number, or 'Unlimited'.
`t`tIf omitted, the default value is unlimited.
`t-Server
`t`tSpecifies the target Exchange server.
`t-------------------------- EXAMPLES ----------------------------
C:\PS> .\HighItemsUsers.ps1 -Server "MyEx2007Server" -OutputFile output.csv -CriticalFoldersOnly `$false
C:\PS> .\HighItemsUsers.ps1 -Database "MyEx2007Server\My Storage Group\My Database"
C:\PS> .\HighItemsUsers.ps1
REMARKS:
`tIf -Database and -Server are omitted, the entire Organization
`twill be checked. "@
}
####################################################################################################
# Script starts here
####################################################################################################
# Check for Usage Statement Request
$args | foreach { if (IsHelpRequest $_) { Usage; exit; } }
#Declare the arrays for holding problem folders.
#The arrays are initialized to "" so that they can be passed by
#reference, even if they contain no objects.
[Array] $2kFolders = ""
[Array] $2k3Folders = ""
[Array] $2k7Folders = ""
[Array] $2k10Folders = ""
#Declare the arrays for keeping track of inaccessible servers and databases.
[Array] $badServers = @()
[Array] $badDBs = @()
[Array] $goodServers = @()
[Array] $goodDBs = @()
#Declare the item count limits we are looking for
if ($ItemCount -gt -1)
{
$2kmax = $ItemCount
$2k3max = $ItemCount
$2k7max = $ItemCount
$2k10max = $ItemCount
}
else
{
$2kmax = 5000
$2k3max = 5000
$2k7max = 20000
$2k10max = 100000
}
#Declare variables for keeping track of progress
[int32]$mbxSucceeded = 0
[int32]$mbxCount = $mbxCmd.Count
[int32]$mbxFailed = 0
#Determine which Get-Mailbox command to run
$getMbxString = "Get-Mailbox -ResultSize $ResultSize"
if ($Server -ne "")
{
$getMbxString += " -Server $Server"
}
elseif ($Database -ne "")
{
$getMbxString += " -Database '$Database'"
}
else
{
#Do nothing. Use the default command
}
if ($DomainController -ne "")
{
$getMbxString += " -DomainController $DomainController"
}
#This array will hold just the properties we need for each mailbox. This helps to conserve memory
$mailboxes = @()
#Start our progress bar
Write-Progress -Activity "Getting All Mailboxes in the Specified Scope" -Status "Command: $getMbxString"
#Actually run the command and store the output in $mailboxes
Invoke-Expression -Command $getMbxString | ForEach-Object{
$ver = getExchangeVersion -mbx ([ref]$_)
$mbx = New-Object PSObject
$mbx | Add-Member NoteProperty Identity $_.Identity.ToString()
$mbx | Add-Member NoteProperty Alias $_.Alias.ToString()
$mbx | Add-Member NoteProperty ServerName $_.ServerName.ToString()
$mbx | Add-Member NoteProperty Database $_.Database.ToString()
$mbx | Add-Member NoteProperty ExchangeVersion $ver
$mailboxes += $mbx
}
#Close progress bar
Write-Progress -Activity "Getting All Mailboxes in the Specified Scope" -Completed -Status "Completed"
#Get total mailbox count
$mbxCount = $mailboxes.Count
#Begin processing of mailboxes
foreach ($mailbox in $mailboxes)
{
#Update Progress Bar
$failCountBefore = $mbxFailed
Write-Progress -Activity "Checking $mbxCount Mailboxes for High Item Counts" -Status "Mailboxes Successfully Processed: $mbxSucceeded Inaccessible Mailboxes: $mbxFailed"
#Check whether the server and database of this mailbox are accessible (only works on 2007 and higher)
if (!(checkAccessibility -badServers ([ref]$badServers) -badDBs ([ref]$badDBs) -goodServers ([ref]$goodServers) -goodDBs ([ref]$goodDBs) -mbxFailed ([ref]$mbxFailed) -mbx $mailbox))
{
#We failed the accessibility check. Skip this mailbox.
Continue
}
#Now on to the actual item checking
#Mailbox version is Exchange 2000
if ($mailbox.ExchangeVersion -eq "2000")
{
checkFolderItems -mbx $mailbox -fldrArray ([ref]$2kFolders) -mbxFailed ([ref]$mbxFailed)
}
#Mailbox version is Exchange 2003
elseif ($mailbox.ExchangeVersion -eq "2003")
{
checkFolderItems -mbx $mailbox -fldrArray ([ref]$2k3Folders) -mbxFailed ([ref]$mbxFailed)
}
#Mailbox version is Exchange 2007
elseif ($mailbox.ExchangeVersion -eq "2007")
{
checkFolderItems -mbx $mailbox -fldrArray ([ref]$2k7Folders) -mbxFailed ([ref]$mbxFailed)
}
#Mailbox version is Exchange 2010
elseif ($mailbox.ExchangeVersion -eq "2010")
{
checkFolderItems -mbx $mailbox -fldrArray ([ref]$2k10Folders) -mbxFailed ([ref]$mbxFailed)
}
if ($failCountBefore -eq $mbxFailed)
{
$mbxSucceeded++
}
}
#Done processing mailboxes. Stop the progress bar
Write-Progress -Activity "Checking $mbxCount Mailboxes for High Item Counts" -Completed -Status "Completed"
#Initialize the Output File
$usingOutput = $false
if ($OutputFile -ne "")
{
$usingOutput = $true "Alias`tFolderPath`tItemsInFolder`tDatabase`tExchangeVersion" | Out-File $OutputFile
}
#Sort all the folders based on item count
Write-Progress -Activity "Sorting Folders by Item Count" -Status " "
$2kFolders = $2kFolders | Sort-Object -Property ItemCount -Descending
$2k3Folders = $2k3Folders | Sort-Object -Property ItemCount -Descending
$2k7Folders = $2k7Folders | Sort-Object -Property ItemCount -Descending
$2k10Folders = $2k10Folders | Sort-Object -Property ItemCount -Descending
Write-Progress -Activity "Sorting Folders by Alias" -Completed -Status "Completed"
#Start writing folder output
$totalFolders = 0
#Write Exchange 2000 Folders to Screen and Output File
if ($2kFolders[0] -ne "")
{
writeOutput ([ref]$2kFolders)
$totalFolders += $2kFolders.Length
}
#Write Exchange 2003 Folders to Screen and Output File
if ($2k3Folders[0] -ne "")
{
writeOutput ([ref]$2k3Folders)
$totalFolders += $2k3Folders.Length
}
#Write Exchange 2007 Folders to Screen and Output File
if ($2k7Folders[0] -ne "")
{
writeOutput ([ref]$2k7Folders)
$totalFolders += $2k7Folders.Length
}
#Write Exchange 2010 Folders to Screen and Output File
if ($2k10Folders[0] -ne "")
{
writeOutput ([ref]$2k10Folders)
$totalFolders += $2k10Folders.Length
}
#Write final statistics to screen
Write-Host ""
Write-Host -ForeGroundColor Green "Finished Processing Mailboxes"
Write-Host -ForeGroundColor yellow "Total Mailboxes Found: " -NoNewLine
Write-Host "$mbxCount"
Write-Host -ForeGroundColor yellow "Mailboxes Successfully Processed: " -NoNewLine
Write-Host "$mbxSucceeded"
Write-Host -ForeGroundColor yellow "Mailboxes Skipped: " -NoNewLine
Write-Host "$mbxFailed"
Write-Host -ForeGroundColor yellow "High Item Folders Found: " -NoNewLine
Write-Host "$totalFolders"