Sunday, January 18, 2009

Summarize MailStore growth and whitespace by Storage Group and growth exception reporting

This script takes a slightly different approach on some of the mailstore size and whitespace scripts that I've posted and a few others you may have seen posted around the traps. The great thing about scripting in the time of the WFC is that its free no budget required and the only limitation to what you can do is probably 1. your imagination 2. your skills. Given the WFC you should have much more time now to improve both (well at least the second). One of the new pressures that some admins maybe feeling in said WFC and the push towards virtulization is that the ratio of Servers to Admin is increasing so companies can at least from some perspective say they are cutting cost and raising efficacy of their IT teams.

So what does this have to do with this script well... because its a new year its a good chance to review and rethink traditional approaches. Pretty much any size reporting script you will see will look at giving you the current size of various components of your mailboxes/mailstore possible whitespace and retained items. This is where most scripters/developers stop, some may record this information in a database which is a great idea because you can then start to look at some growth trends. When you have a larger number of Servers, Stores and possibly Organizations if your a service provider just looking at recorded size information while usefull when its gets to large quantities it can be very hard for people to spot any anomalies or areas of interest that may need further investigation. Its also may lead to the discounting of such information by your more junior engineers if you can't provide a more valuable representation of the data your collecting with your scripts. The other users of this information your recording maybe your more senior managers who mostly like nice shiny reports but size reports that don't reflect the nature of change of the underlying system means its missing the point. If your size reports where written a few years ago and have had no changes since then you should get your finger out and your thinking cap on.

My approach to rewriting scripts from the traditional approach is first to make your script record historical data. The two options for doing this is firstly use a database which is a great idea because you can then use higher level reporting tools and SQL. The other option for recording historical information is using history files which is a good option where a database isn't practical which is the case for a lot of environments it also makes your scripting self contained and write once run everywhere so this is the approach I favour. To reduce information overload you should look at summarising data where you can. With this script I've summarised the size/whitespace data by Storage Group. This means if you have a large number of Storage groups spreed across a large number of servers you can a more manageable report. To do the data summerization I've use Custom objects and nested hashtables and a little bit of Math. The result of each run are written to a history file in a history directory which is used then to do exception and growth reporting.

Exception and growth reporting sounds hard but not really basically first there is some code that reads in the all the history file names that are in the history directory and then determines which file will represent the data from 1day 7days and 30days. Its then reads in each of these files into nested hashtable and index's it by combining the ServerName and StorageGroup. Then when the script runs through and builds the normal size report at the same time the current size is checked against the previous sizes and compaired against Threshold varibles. If any of the thresholds are breeched the an entry is added the the thresholds exception table.

Okay so to put all this togther into something thats usefull the script uses the Get-mailboxServer cmdlet to feed the servername of each of the mailbox servers within a Exchange Org into a function that then goes out and queries the size of the Mailbox and Public Folder Stores and then tries to use WMI to query the event logs this process is explained in a previous post. The results are combined into a HTML body of email and then the result is sent via SMTP to a mailbox (of a person who hopefully get some use from it). What gets emailed is firstly a table of all the Storage Group sizes summaries with WhiteSpace information. Then any exceptions are added after this first table. Before running the script you should set the following thresholds all sizes are in MB

$StoreSizeThreshold1day = 100
$StoreSizeThreshold7day = 300
$StoreSizeThreshold30day = 1000

$WhiteSpaceThreshold1day = 100
$WhiteSpaceThreshold7day = 300
$WhiteSpaceThreshold30day = 1000

$SMTPservername = "smtpservername"
$Toaddress = "your@ydomain.com"
$fromAddress = "Report@ydomain.com"

The script will store the history file in the c:\sizehistory directory based on this line

$HistoryDir = "c:\sizehistory"

I've put a download of this script here the script itself looks like

$StoreSizeThreshold1day = 100
$StoreSizeThreshold7day = 300
$StoreSizeThreshold30day = 1000

$WhiteSpaceThreshold1day = 100
$WhiteSpaceThreshold7day = 300
$WhiteSpaceThreshold30day = 1000

$SMTPservername = "192.168.1.45"
$Toaddress = "your@ydomain.com"
$fromAddress = "Report@ydomain.com"

function GetWSforServer($snServerName){

$SgcombCollection = @()
"Querying Server : " + $snServerName

$StoreFileSizes = @{ }
$StoreWhitespace = @{ }
$StoreRetainItemSize = @{ }
$StoreDeletedMailboxSize = @{ }
$sgTotalHash = @{ }
$hcHourCount = @{ }
$root = [ADSI]'LDAP://RootDSE'
$cfConfigRootpath = "LDAP://" + $root.ConfigurationNamingContext.tostring()
$configRoot = [ADSI]$cfConfigRootpath
$searcher = new-object System.DirectoryServices.DirectorySearcher($configRoot)
$searcher.Filter = '(&(objectCategory=msExchExchangeServer)(cn=' + $snServerName + '))'
$searchres = $searcher.FindOne()
$snServerEntry = New-Object System.DirectoryServices.directoryentry
$snServerEntry = $searchres.GetDirectoryEntry()




$adsiServer = [ADSI]('LDAP://' + $snServerEntry.DistinguishedName)
$dfsearcher = new-object System.DirectoryServices.DirectorySearcher($adsiServer)
$dfsearcher.Filter = "(objectCategory=msExchPrivateMDB)"
$srSearchResults = $dfsearcher.FindAll()
foreach ($srSearchResult in $srSearchResults){
$msMailStore = $srSearchResult.GetDirectoryEntry()
$sgStorageGroup = $msMailStore.psbase.Parent
if ($sgStorageGroup.msExchESEParamBaseName -ne "R00"){
$edbfile = [WMI]("\\" + $snServerName + "\root\cimv2:CIM_DataFile.Name='" + $msMailStore.msExchEDBFile + "'")
$StoreFileSize = [math]::round($edbfile.filesize/1048576,0)
$exStoreName = ($sgStorageGroup.Name.ToString() + "\" + $msMailStore.Name.ToString())
$StoreFileSizes.Add($exStoreName,$StoreFileSize)
}
}
"Finshed Mailstores"
$dfsearcher.Filter = "(objectCategory=msExchPublicMDB)"
$srSearchResults = $dfsearcher.FindAll()
foreach ($srSearchResult in $srSearchResults){
$msMailStore = $srSearchResult.GetDirectoryEntry()
$sgStorageGroup = $msMailStore.psbase.Parent
if ($sgStorageGroup.msExchESEParamBaseName -ne "R00"){
$edbfile = [WMI]("\\" + $snServerName + "\root\cimv2:CIM_DataFile.Name='" + $msMailStore.msExchEDBFile + "'")
$StoreFileSize = [math]::round($edbfile.filesize/1048576,0)
$exStoreName = ($sgStorageGroup.Name.ToString() + "\" + $msMailStore.Name.ToString())
$StoreFileSizes.Add($exStoreName,$StoreFileSize)
}
}
"Finshed Public Folder Stores"
$WmidtQueryDT = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime([DateTime]::UtcNow.AddDays(-3))
Get-WmiObject -computer $snServerName -query ("Select * from Win32_NTLogEvent Where Logfile='Application' and Eventcode = '1221' and TimeWritten >='" + $WmidtQueryDT + "'") | sort $_.TimeWritten -Descending |
foreach-object{
$mbnamearray = $_.message.split("`"")
$esEndString = $mbnamearray[2].indexof("megabytes ")-6
if ($StoreWhitespace.Containskey($mbnamearray[1]) -eq $false){
$StoreWhitespace.Add($mbnamearray[1],$mbnamearray[2].Substring(5,$esEndString))
}
}
"Finished WhiteSpace"
$WmidtQueryDT = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime([DateTime]::UtcNow.AddDays(-3))
Get-WmiObject -computer $snServerName -query ("Select * from Win32_NTLogEvent Where Logfile='Application' and Eventcode = '1207' and TimeWritten >='" + $WmidtQueryDT + "'") | sort $_.TimeWritten -Descending |
foreach-object{
$mbnamearray = $_.message.split("`"")
$enditem = $mbnamearray[2].Substring($mbnamearray[2].indexof("End:"))
$esize = $enditem.SubString($enditem.indexof("items")+7,$enditem.indexof(" Kbytes")-($enditem.indexof("items")+7))
if ($StoreRetainItemSize.Containskey($mbnamearray[1]) -eq $false){
$StoreRetainItemSize.Add($mbnamearray[1],[math]::round(($esize/1024),0))
}

}
"Finshed Retained Items"
$WmidtQueryDT = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime([DateTime]::UtcNow.AddDays(-3))
Get-WmiObject -computer $snServerName -query ("Select * from Win32_NTLogEvent Where Logfile='Application' and Eventcode = '9535' and TimeWritten >='" + $WmidtQueryDT + "'") | sort $_.TimeWritten -Descending |
foreach-object{
$mbnamearray = $_.message.split("`"")
$retMbs = $mbnamearray[2].Substring($mbnamearray[2].indexof("have been removed."))
$retMbsSize = $retMbs.Substring(($retMbs.indexof("(")+1),$retMbs.indexof(")")-($retMbs.indexof("(")+1)).Replace(" KB","")
if ($StoreDeletedMailboxSize.Containskey($mbnamearray[1]) -eq $false){
$StoreDeletedMailboxSize.Add($mbnamearray[1],[math]::round(($retMbsSize/1024),0))
}

}
$StoreFileSizes.GetEnumerator() | sort name -descending | foreach-object {
$snames = $_.key.split("\")
if ($sgTotalHash.containsKey($snames[0])){
if ($StoreDeletedMailboxSize.containskey($_.key)){
$sgTotalHash[$snames[0]].MailboxStores = [int]$sgTotalHash[$snames[0]].MailboxStores + 1
$sgTotalHash[$snames[0]].MSSize = [int]$sgTotalHash[$snames[0]].MSSize + [int]$_.Value
$sgTotalHash[$snames[0]].MSWhiteSpace = [int]$sgTotalHash[$snames[0]].MSWhiteSpace + [int]$StoreWhitespace[$_.key].ToString()
$sgTotalHash[$snames[0]].MSRetainedItems = [int]$sgTotalHash[$snames[0]].RetainedItems + [int]$StoreRetainItemSize[$_.key].ToString()
$sgTotalHash[$snames[0]].RetainedMB = [int]$sgTotalHash[$snames[0]].RetainedMB + [int]$StoreDeletedMailboxSize[$_.key].ToString()

}
else{
$sgTotalHash[$snames[0]].PublicFolderStores = [int]$sgTotalHash[$snames[0]].MailboxStores + 1
$sgTotalHash[$snames[0]].PFSize = [int]$sgTotalHash[$snames[0]].MSSize + [int]$_.Value
$sgTotalHash[$snames[0]].PFWhiteSpace = [int]$sgTotalHash[$snames[0]].MSWhiteSpace + [int]$StoreWhitespace[$_.key].ToString()
$sgTotalHash[$snames[0]].PFRetainedItems = [int]$sgTotalHash[$snames[0]].RetainedItems + [int]$StoreRetainItemSize[$_.key].ToString()

}

}
else{
$sgtotalObject = "" | select ServerName,Name,MailboxStores,PublicFolderStores,MSSize,PFSize,MSWhiteSpace,PFWhiteSpace,MSRetainedItems,PFRetainedItems,RetainedMB
$sgtotalObject.ServerName = $snServerName
$sgtotalObject.Name = $snames[0]
if ($StoreDeletedMailboxSize.containskey($_.key)){
$sgtotalObject.MailboxStores = 1
$sgtotalObject.PublicFolderStores = 0
$sgtotalObject.MSSize = $_.Value.ToString()
$sgtotalObject.PFSize = 0
$sgtotalObject.MSWhiteSpace = $StoreWhitespace[$_.key].ToString()
$sgtotalObject.PFWhiteSpace = 0
$sgtotalObject.MSRetainedItems = $StoreRetainItemSize[$_.key].ToString()
$sgtotalObject.PFRetainedItems = 0
$sgtotalObject.RetainedMB = $StoreDeletedMailboxSize[$_.key].ToString()
}
else {
$sgtotalObject.MailboxStores = 0
$sgtotalObject.PublicFolderStores = 1
$sgtotalObject.MSSize = 0
$sgtotalObject.PFSize = $_.Value.ToString()
$sgtotalObject.MSWhiteSpace = 0
$sgtotalObject.PFWhiteSpace = $StoreWhitespace[$_.key].ToString()
$sgtotalObject.MSRetainedItems = 0
$sgtotalObject.PFRetainedItems = $StoreRetainItemSize[$_.key].ToString()
$sgtotalObject.RetainedMB = 0
}

$sgTotalHash.Add($snames[0],$sgtotalObject)
}

}



foreach ($row in $sgTotalHash.Values){
$global:rpReport = $global:rpReport + " <tr>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $snServerName + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.Name.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.MailboxStores.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.PublicFolderStores.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.MSSize.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.PFSize.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.MSWhiteSpace.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.PFWhiteSpace.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.MSRetainedItems.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.PFRetainedItems.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.RetainedMB.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "</tr>" + "`r`n"
$global:ExcombCollection += $row
if ($onedaystats.Containskey(($snServerName + "\" + $row.Name.ToString()))){
$onedaystats[($snServerName + "\" + $row.Name.ToString())].MSSize
if(([INT]$row.MSSize - [INT]$onedaystats[($snServerName + "\" + $row.Name.ToString())].MSSize) -gt $StoreSizeThreshold1day){
writeThresholdExecption "One Day MailStore Size" $snServerName $row.Name.ToString() $row.MSSize $onedaystats[($snServerName + "\" + $row.Name.ToString())].MSSize.ToString()
}
if(([INT]$row.PFSize - [INT]$onedaystats[($snServerName + "\" + $row.Name.ToString())].PFSize) -gt $StoreSizeThreshold1day){
writeThresholdExecption "One Day PublicStore Size" $snServerName $row.Name.ToString() $row.PFSize $onedaystats[($snServerName + "\" + $row.Name.ToString())].PFSize.ToString()
}
if(([INT]$row.MSWhiteSpace - [INT]$onedaystats[($snServerName + "\" + $row.Name.ToString())].MSWhiteSpace) -gt $WhiteSpaceThreshold1day){
writeThresholdExecption "One Day Mail Store WhiteSpace" $snServerName $row.Name.ToString() $row.MSWhiteSpace $onedaystats[($snServerName + "\" + $row.Name.ToString())].MSWhiteSpace.ToString()
}
if(([INT]$row.PFWhiteSpace - [INT]$onedaystats[($snServerName + "\" + $row.Name.ToString())].PFWhiteSpace) -gt $WhiteSpaceThreshold1day){
writeThresholdExecption "One Day Public Store WhiteSpace" $snServerName $row.Name.ToString() $row.PFWhiteSpace $onedaystats[($snServerName + "\" + $row.Name.ToString())].PFWhiteSpace.ToString()
}

}
if ($onedaystats.Containskey(($snServerName + "\" + $row.Name.ToString()))){
$sevendaystats[($snServerName + "\" + $row.Name.ToString())].MSSize
if(([INT]$row.MSSize - [INT]$sevendaystats[($snServerName + "\" + $row.Name.ToString())].MSSize) -gt $StoreSizeThreshold7day){
writeThresholdExecption "Seven Day MailStore Size" $snServerName $row.Name.ToString() $row.MSSize $sevendaystats[($snServerName + "\" + $row.Name.ToString())].MSSize.ToString()
}
if(([INT]$row.PFSize - [INT]$sevendaystats[($snServerName + "\" + $row.Name.ToString())].PFSize) -gt $StoreSizeThreshold7day){
writeThresholdExecption "Seven Day Public Store Size" $snServerName $row.Name.ToString() $row.PFSize $sevendaystats[($snServerName + "\" + $row.Name.ToString())].PFSize.ToString()
}
if(([INT]$row.MSWhiteSpace - [INT]$sevendaystats[($snServerName + "\" + $row.Name.ToString())].MSWhiteSpace) -gt $WhiteSpaceThreshold7day){
writeThresholdExecption "Seven Day Mail Store WhiteSpace" $snServerName $row.Name.ToString() $row.MSWhiteSpace $sevendaystats[($snServerName + "\" + $row.Name.ToString())].MSWhiteSpace.ToString()
}
if(([INT]$row.PFWhiteSpace - [INT]$sevendaystats[($snServerName + "\" + $row.Name.ToString())].PFWhiteSpace) -gt $WhiteSpaceThreshold7day){
writeThresholdExecption "Seven Day Public Store WhiteSpace" $snServerName $row.Name.ToString() $row.PFWhiteSpace $sevendaystats[($snServerName + "\" + $row.Name.ToString())].PFWhiteSpace.ToString()
}
}
if ($onemonthsstats.Containskey(($snServerName + "\" + $row.Name.ToString()))){
$onemonthsstats[($snServerName + "\" + $row.Name.ToString())].MSSize
if(([INT]$row.MSSize - [INT]$onemonthsstats[($snServerName + "\" + $row.Name.ToString())].MSSize) -gt $StoreSizeThreshold30day){
writeThresholdExecption "Thirty Day MailStore Size" $snServerName $row.Name.ToString() $row.MSSize $onemonthsstats[($snServerName + "\" + $row.Name.ToString())].MSSize.ToString()
}
if(([INT]$row.PFSize - [INT]$onemonthsstats[($snServerName + "\" + $row.Name.ToString())].PFSize) -gt $StoreSizeThreshold30day){
writeThresholdExecption "Thirty Day Public Store Size" $snServerName $row.Name.ToString() $row.PFSize $onemonthsstats[($snServerName + "\" + $row.Name.ToString())].PFSize.ToString()
}
if(([INT]$row.MSWhiteSpace - [INT]$onemonthsstats[($snServerName + "\" + $row.Name.ToString())].MSWhiteSpace) -gt $WhiteSpaceThreshold30day){
writeThresholdExecption "Thirty Day MailStore WhiteSpace" $snServerName $row.Name.ToString() $row.MSWhiteSpace $onemonthsstats[($snServerName + "\" + $row.Name.ToString())].MSWhiteSpace.ToString()
}
if(([INT]$row.PFWhiteSpace - [INT]$onemonthsstats[($snServerName + "\" + $row.Name.ToString())].PFWhiteSpace) -gt $WhiteSpaceThreshold30day){
writeThresholdExecption "Thirty Day Public Store WhiteSpace" $snServerName $row.Name.ToString() $row.PFWhiteSpace $onemonthsstats[($snServerName + "\" + $row.Name.ToString())].PFWhiteSpace.ToString()
}
}
}


}

function writeThresholdExecption([String]$threshold,[String]$tsServerName,[String]$tsSGName,[String]$tscValue,[String]$tspValue) {
$global:expReport = $global:expReport + " <tr>" +"`r`n"
$global:expReport = $global:expReport + "<td>" + $threshold + "</td>" +"`r`n"
$global:expReport = $global:expReport + "<td>" + $tsServerName + "</td>" +"`r`n"
$global:expReport = $global:expReport + "<td>" + $tsSGName + "</td>" +"`r`n"
$global:expReport = $global:expReport + "<td>" + $tscValue + "</td>" +"`r`n"
$global:expReport = $global:expReport + "<td>" + $tspValue + "</td>" +"`r`n"
$global:expReport = $global:expReport + "<td>" + ([INT]$tscValue - [INT]$tspValue) + "</td>" +"`r`n"
$global:expReport = $global:expReport + "</tr>" + "`r`n"

}



$HistoryDir = "c:\sizehistory"

if (!(Test-Path -path $HistoryDir))
{
New-Item $HistoryDir -type directory
}
$global:rpReport = ""
$global:expReport = ""
$global:rpReport = $global:rpReport + "<table><tr bgcolor=`"#95aedc`">" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>ServerName</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:15%;`" ><b>SG Name</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:5%;`" ><b>MS #</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:5%;`" ><b>PFS #</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>MS Size</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>PF Size</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>MSWSpace</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>PFWpace</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>MSRetItems</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>PFRetItems</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>RetMB</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "</tr>" + "`r`n"
$global:expReport = $global:expReport + "<table><tr bgcolor=`"#95aedc`">" +"`r`n"
$global:expReport = $global:expReport + "<td align=`"center`" style=`"width:15%;`" ><b>Threshold</b></td>" +"`r`n"
$global:expReport = $global:expReport + "<td align=`"center`" style=`"width:15%;`" ><b>ServerName</b></td>" +"`r`n"
$global:expReport = $global:expReport + "<td align=`"center`" style=`"width:15%;`" ><b>SGName</b></td>" +"`r`n"
$global:expReport = $global:expReport + "<td align=`"center`" style=`"width:10%;`" ><b>Current Value</b></td>" +"`r`n"
$global:expReport = $global:expReport + "<td align=`"center`" style=`"width:10%;`" ><b>Previous Value</b></td>" +"`r`n"
$global:expReport = $global:expReport + "<td align=`"center`" style=`"width:10%;`" ><b>Growth</b></td>" +"`r`n"
$global:expReport = $global:expReport + "</tr>" + "`r`n"
$global:ExcombCollection = @()
$datetime = get-date
$arArrayList = New-Object System.Collections.ArrayList
dir $script:HistoryDir\*.csv | foreach-object{
$fname = $_.name
$nmArray = $_.name.split("-")
[VOID]$arArrayList.Add($nmArray[0])
}
$arArrayList.Sort()
$spoint = $arArrayList[$arArrayList.Count-1]
$oneday = $spoint
$sevenday = $spoint
$onemonth = $spoint
$oneyear = $spoint
foreach ($file in $arArrayList){
if ($file -gt ($datetime.Adddays(-2).ToString("yyyyMMdd")) -band $file -lt $oneday) {$oneday = $file}
if ($file -gt ($datetime.Adddays(-7).ToString("yyyyMMdd")) -band $file -lt $sevenday) {$sevenday = $file}
if ($file -gt ($datetime.Adddays(-31).ToString("yyyyMMdd")) -band $file -lt $onemonth) {$onemonth = $file}
}

$onedaystats = @{ }
$sevendaystats = @{ }
$onemonthsstats = @{ }
$oneyearstats = @{ }

Import-Csv ("$script:HistoryDir\" + $oneday + "-wspacerun.csv") | %{
$onedaystats.add(($_.ServerName.ToString() + "\" + $_.Name.ToString()),$_)
}
Import-Csv ("$script:HistoryDir\" + $sevenday + "-wspacerun.csv") | %{
$sevendaystats.add(($_.ServerName.ToString() + "\" + $_.Name.ToString()),$_)
}
Import-Csv ("$script:HistoryDir\" + $onemonth + "-wspacerun.csv") | %{
$onemonthsstats.add(($_.ServerName.ToString() + "\" + $_.Name.ToString()),$_)
}


Get-MailboxServer | foreach-object{
GetWSforServer($_.Name.ToString())
}
$datetime = get-date
$fname = $script:HistoryDir + "\"
$fname = $fname + $datetime.ToString("yyyyMMdd") + "-wspacerun.csv"
$global:ExcombCollection | export-csv –encoding "unicode" -noTypeInformation $fname
$global:rpReport = $global:rpReport + "</table>" + " <BR><BR><H1>Threshold Exceeds</H1><BR> "
$global:rpReport = $global:rpReport + $global:expReport
$global:rpReport = $global:rpReport + "</table>" + " <BR><BR> "

$SmtpClient = new-object system.net.mail.smtpClient
$SmtpClient.host = $SMTPservername
$MailMessage = new-object System.Net.Mail.MailMessage
$MailMessage.To.Add($ToAddress)
$MailMessage.From = $FromAddress
$MailMessage.Subject = "Storage Group Reports"
$MailMessage.IsBodyHtml = $TRUE
$MailMessage.body = $global:rpReport
$SMTPClient.Send($MailMessage)
write-host "Mail Sent"

20 comments:

Gennady said...

Hey, I have a bug on running this script.

File 'c:\sizehistory\-wspacerun.csv' not found.

String 285, position 11.


Should I have any prerequisites for use this script?

Glen said...

Thanks there was a problem on the first run if this directory didn't exist. I've updated the download so it bypasses the growth check the first time it runs so you shouldn't get this error.

Cheers
Glen

Gennady said...

It's seems that nothing changed in your script (on site and in download archive): I have the same error.

Glen said...

I check the download is okay maybe a caching issue on your end ? you should see


if ($frun -eq 0){

in the new script. You also shouldn't get the error on the second run the script will try to create a directory on the c: drive called sizehistory if it can't do this (eg rights) then you would continue to get this error so you may need to manually create this directory.

Cheers
Glen

Anonymous said...

Fantastic post. I actually created a HTMl report for my ORG based on your previous post on whitespace/DB sizes.

After mgt appreciated its potential, It is now being upgraded to to a more advanced report with DB integration. (not by me may I add but a real developer)

Anyway, please keep posting these ideas and examples!

Gennady said...

Glen, thx!

All working now. It's was my error. I go deep in logic of script and all became fine.

Littlt syntax bug: on string 254 "PFWpace" should be "PFSWpace".

Mike said...

seemed to be running fine until it got to the Send:

Exception calling "Send" with "1" argument(s): "Failure sending mail."
At D:\wspsumexc.ps1:319 char:17
+ $SMTPClient.Send( <<<< $MailMessage)

any ideas?

Mike said...

ignore my previous comment. I ran it on my laptop, and the mcafee client blocks port 25.

DJ said...

Is there anyway this can be exported into an excel sheet which saves the time of copy & paste to be able to sort the data?

Thanks!

Glen said...

Use the Export gird button which should export this grid to a CSV file which you can then access in Excel.

Cheers
Glen

Anonymous said...

Hello, is it possible to run this script against a mixed 2k4\2k7 enviroment.
When i run the script i only get data for the 2k7 servers?

Glen said...

It should run fine as is only uses ADSI and WMI to get the information. The restriction is it will only get information from servers within one forest.

Cheers
Glen

Anonymous said...

The script seems to select the first e2k7 server, this server is not contactable (firewall, etc) it then fails to return any data from the e2k3 servers, the scipt seems to fail after the retained items with the following type of errors

"You cannot call a method on a null-valued expression.
At D:\wspsumexc.ps1:139 char:68
+ $sgtotalObject.PFWhiteSpace = $StoreWhitespace[$_.key].ToString(
You cannot call a method on a null-valued expression."

i am assuming because the e2k7 server is not contactable using rpc
is there a way to exclude the e2k7 servers?

Glen said...

You could try using $ErrorActionPreference = "SilentlyContinue"

to jump over the errors. If you want to exclude paricular server put a if statement based on the name or check the version property in AD.

Cheers
Glen

Tomy said...

Nice script..it works well for E2K7 servers..Is there any way to query E2k3 servers also ?

where should i put the below statement to continue on error ?
$ErrorActionPreference = "SilentlyContinue"
Also what statement i have to put for exlcluding some servers and where ?

Glen said...

Put that line as the first line in the script

It will work with either 2003 or 2007 it just use ADSI and WMI

Cheers
Glen

David Allen said...

Hi Glen - this is a great script. Is there an easy way to add the query for number of users per database? I have found some code that gives me that info but am unsure how to add it to the columns.
-David

Glen said...

This script doesn't look at the user side of the Database so not easy but it could be done but you would have to add new querys in.

Cheers
Glen

John Brines said...

Hi Glen,

Great Script.

Would it be possible to add a column that shows the percentage of the WhiteSPace against the database size?

John.

Anonymous said...

I know this is an old script but is it possible to make it function on Exchange 2010?