Monday, June 18, 2007

Script: Identifying Quota Bottlenecks

Quota increase requests are a frequent occurrence for me. Without blindly approving the request, I prefer to look for large folders within a users’ mailbox that could easily be archived (e.g. ‘Sent Items 05’ or ‘Archived Items’). I have used the following scripts to see the number of items and size of user mailbox folders.

Exchange 2007


The Exchange Management Shell offers some built-in tools to accomplish this task. Massaging the output makes it easier to identify quota bottlenecks. This script can be run from any computer with the Exchange Management Shell

The Script:
param($alias = $(read-host alias))
Get-MailboxFolderStatistics $alias | FT FolderPath,ItemsInFolder,@{label="FolderSize (KB)";expression={$_.FolderSize.ToKB()} }
Get-MailboxStatistics $alias | FT ItemCount,StorageLimitStatus,@{label="TotalItemSize (KB)";expression={$_.TotalItemSize.Value.ToKB()} },@{label="TotalItemSize (MB)";expression={$_.TotalItemSize.Value.ToMB()} },LastLogonTime


The Output:


[PS] C:\Temp>.\MailboxSize.ps1 e12_test1

FolderPath ItemsInFolder FolderSize (KB)
---------- ------------- ---------------
/ 0 0
/Calendar 5 33
/Contacts 0 0
/Deleted Items 10 9
/Drafts 0 0
/Inbox 10 79356
/Journal 0 0
/Junk E-Mail 0 0
/Notes 0 0
/Outbox 0 0
/RSS Feeds 0 0
/Sent Items 14 32
/Sync Issues 0 0
/Sync Issues/Conflicts 0 0
/Sync Issues/Local Fail... 0 0
/Sync Issues/Server Fai... 0 0
/Tasks 0 0

ItemCount StorageLimitStatus TotalItemSize (KB) TotalItemSize (MB) LastLogonTime
--------- ------------------ ------------------ ------------------ -------------
43 BelowLimit 79438 77 6/6/2007 2:03:07 PM




 


Exchange 2003


The attached VBScript must be run on the mailbox server hosting the user’s mailbox. It connects to the IFS drive and evaluates the size of each folder in the user’s mailbox. I modified a script previously published by Glen Scales and adapted it to output the name and total size of the folder to the command window.

**Remember to change your domain name on line 15**

The Script:
'Adapted from http://www.outlookexchange.com/articles/glenscales/mreport2.asp


Dim obArgs,cArgs,iSize,ndate,tmailbox

Set obArgs = WScript.Arguments
tmailbox = obArgs.Item(0)

Main

Sub Main()
Dim sConnString,domainname

'On Error Resume Next
domainname = "mail.domain.com"
' Set up connection string to mailbox.
sConnString = "file://./backofficestorage/" & domainname
sConnString = sConnString & "/mbx/" & obArgs.Item(0) & "/NON_IPM_SUBTREE"

iSize = 0
Wscript.Echo
RecurseFolder sConnString, ""
WScript.Echo
WScript.Echo "Mailbox Size: " & replace(formatnumber((iSize/1024/1024),2),",","") & " MB"
End Sub


Public Sub RecurseFolder(sConnString, sParentFolder)
Dim oConn
Dim oRecSet
Dim sSQL
Dim sFolderPath

' Set up SQL SELECT statement.
sSQL = "SELECT ""http://schemas.microsoft.com/mapi/proptag/x0e080003"", "
sSQL = sSQL & """DAV:href"",""DAV:hassubs"",""DAV:displayname"" "
sSQL = sSQL & "FROM SCOPE ('SHALLOW TRAVERSAL OF """ & sConnString
sSQL = sSQL & """') WHERE ""DAV:isfolder"" = true"

' Create Connection object.
Set oConn = CreateObject("ADODB.Connection")
Set oRecSet = CreateObject("ADODB.Recordset")

' Set provider to EXOLEDB.
oConn.Provider = "Exoledb.DataSource"

' Open connection to folder.
oConn.Open sConnString
if Err.Number <> 0 then
WScript.Echo "Error opening connection: " & Err.Number & " " & Err.Description
Set oRecSet = Nothing
Set oConn = Nothing
Exit Sub
end if

' Open Recordset of all subfolders in folder.
oRecSet.CursorLocation = 3
oRecSet.Open sSQL, oConn.ConnectionString
if Err.Number <> 0 then
WScript.Echo "Error opening recordset: " & Err.Number & " " & Err.Description
oRecSet.Close
oConn.Close
Set oRecSet = Nothing
Set oConn = Nothing
Exit Sub
end if

if oRecSet.RecordCount = 0 then
oRecSet.Close
oConn.Close
Set oRecSet = Nothing
Set oConn = Nothing
Exit Sub
end if

' Move to first record.
oRecSet.MoveFirst
if Err.Number <> 0 then
WScript.Echo "Error moving to first record: " & Err.Number & " " & Err.Description
oRecSet.Close
oConn.Close
Set oRecSet = Nothing
Set oConn = Nothing
Exit Sub
end if


' Loop through all of the records, and then add the size of the
' subfolders to obtain the total size.
While oRecSet.EOF <> True
' Increment size.
iSize = iSize + oRecSet.Fields.Item("http://schemas.microsoft.com/mapi/proptag/x0e080003")
foldersize = oRecSet.Fields.Item("http://schemas.microsoft.com/mapi/proptag/x0e080003")
workfolderfp = oRecSet.Fields("DAV:href").value
workfolder = oRecSet.Fields("DAV:displayname").value
sFolderPath = sParentFolder & "/" & workfolder
if InStr(sConnString,"NON_IPM_SUBTREE") = 0 then
Dim sSplit
sSplit = Split(sFolderPath,"/")
Dim sShortPath
sShortPath = ""
for i = 2 to Ubound(sSplit)
sShortPath = sShortPath & sSplit(i) & "/"
next
Dim sSize, sFolder, sDisplay
sFolder = Left(sShortPath,Len(sShortPath)-1)
sSize = replace(formatnumber((foldersize/1024),0),",","") & " KB"
sDisplay = sFolder & " "
for i = Len(sFolder) to (50 - Len(sSize))
sDisplay = sDisplay & " "
next
sDisplay = sDisplay + sSize
WScript.Echo sDisplay
end if
' If the folder has subfolders, recursively call RecurseFolder to process them.

If oRecSet.Fields.Item("DAV:hassubs") = True then
RecurseFolder oRecSet.Fields.Item("DAV:href"), sFolderPath
End If
' Move to next record.
oRecSet.MoveNext
if Err.Number <> 0 then
WScript.Echo "Error moving to next record: " & Err.Number & " " & Err.Description
Set oRecSet = Nothing
Set oConn = Nothing
Exit Sub
end if
wend

' Close Recordset and Connection.
oRecSet.Close
if Err.Number <> 0 then
WScript.Echo "Error closing recordset: " & Err.Number & " " & Err.Description
Set oRecSet = Nothing
Set oConn = Nothing
Exit Sub
end if

oConn.Close
if Err.Number <> 0 then
WScript.Echo "Error closing connection: " & Err.Number & " " & Err.Description
Set oRecSet = Nothing
Set oConn = Nothing
Exit Sub
end if

' Clean up memory.
Set oRecSet = Nothing
Set oConn = Nothing
End Sub


The Output:


C:\temp>cscript MailboxSize.vbs user.csuf
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.


Inbox 472 KB
Outbox 0 KB
Sent Items 16 KB
Deleted Items 0 KB
Calendar 0 KB
Contacts 0 KB
Drafts 0 KB
Journal 0 KB
Notes 0 KB
Tasks 0 KB
Sync Issues 0 KB
Sync Issues/Conflicts 0 KB
Sync Issues/Local Failures 0 KB
Sync Issues/Server Failures 0 KB
Junk E-mail 1 KB

Mailbox Size: 0.48 MB





Download both scripts

--Nick

2 comments:

WalkaboutTigger said...

Is there no way to programmatically enumerate the number of items in a folder using similar code against Exchange 2003?

Nick Smith said...

WalkaboutTigger,

I've posted an updated copy of the script for Exchange 2003 that displays the folder item count at http://cid-73e0b2e7ecdb6467.skydrive.live.com/self.aspx/Blog%20Files/MailboxSize.zip.

--Nick