Script Info #-------------- # Script Name : Exchange 2010 Organization

advertisement
<#-------------# Script Info
#-------------# Script Name
:
Exchange 2010 Organization Dashboard
# Script Version
:
1.0
# Author
:
Ammar Hasayen based on Steve Goodman's
Exchange Environemnt Report
# Note
:
Steve Goodman wrote the original
script, Ammar Hasayen added extea features
# Blog
:
http://www.stevieg.org ,
http://ammarhasayen.wordpress.com
# Description
:
Generate Exchange Organization Dashboard
Report
#-------------# Copy Rights
#-------------# The script is originally written in its initial version by Steve Goodman. The
original script including commenst can be found
# and download from Steve's blog (http://www.stevieg.org). Any additional code
is written by Ammar Hasayen (http://ammarhasayen.wordpress.com)
#-------------# Script Requirement
#-------------# - The script assumes you have only Exchange 2010 environment. Script also
assumes you have any type of DAG deployment
# - You must run the script with an account that has admin rights on all
Exchange Servers to collect disk and O.S health info
# - Also, the account should have access to read all Exchange Information
(ViewAdministrator)
# - Script may take some time to run depending on your environment
# - Script needs (Microsoft Chart Controls for Microsoft .NET Framework) to be
installed only on the machine that will run the script. This is needed in order
to generate charts
#
Download Microsoft Chart Controls for Microsoft .NET Framework 3.5
(http://www.microsoft.com/en-us/download/details.aspx?id=14422)
# - Script is tested on Windows 2008 R2 with PowerShell 2.0
# - Run the script using one of two methods : 1) Open Exchange 2010 PowerShell
Window, and browse to the script and run it without any parameters
#
2) schedule the script to run daily or weekly using Windows Task Manager.
Check my blog of how to do that
# - The sample scripts are not supported under any support. The sample scripts
are provided AS IS without warranty of any kind.
#>
#-------------# Customization Section
#-------------# Please customize the following :
#
1) In all script body, make sure that you replace all appearance of
"F:\ScheduledScripts\Pilot" with your script working directory
#
2) Set Exchange Thresholds:
#Threshold for Maximum number of mailboxes per database. Color
warning will show otherwise
[int]$MailboxCountThreshold = 800
#Threshold for Size of database in Gigabytes. Color warning will
show otherwise
[double]$DBSizeThreshold = 1200
#Percentage of the database logical disk free space. Color warning
will show if the free space is less than the percentage
[double]$DiskSpaceThreshold = 15
#Threshold for days since last database backup (warning threshold)
. Color warning will show otherwise
[int]$BackupWarning = 100
#Threshold for days since last database backup (Error threshold) .
Color warning will show otherwise
[int]$BackupError = 200
#Threshold for days since Exchange Servers have been restarted
(Numbers represents days) . Color warning will show otherwise
[int]$UptimeErrorThreshold
= 90
[int]$UptimeWarningThreshold = 60
#Threshold for Database Copy Queues (numbers represents number of
logs). Color warning will show otherwise
[int]$ReplayQueueThreshold = 200
[int]$CopyQueueThreshold
= 100
#
3) Set Disk Thresholds:
# C drive thresholds (in GB)
$SystemDriveWarning
= 5
$SystemDriveError
= 3
# Data drives thresholds for non mailbox servers (in GB)
$DataDriveWarning_NM
= 6
$DataDriveError_NM
= 3
# Data drives thresholds for mailbox servers (in GB)
$DataDriveWarning_M
= 150
$DataDriveError_M
= 70
#
4) Set Email Settings
$EmailSender
= "noreply@contoso.com"
$EmailTo
= "Admin@contoso.com"
# You can assign only one smtp address in the EmailTO parameter
$EmailSMTP
= "smtp.contoso.com"
# You ARE DONE CUSTOMIZATION. THANK YOU !
#-------------# END OF Customization Section
#--------------
#----------------------------------# Section 1 - Script Preperation Tasks
#----------------------------------write-host
write-host
write-host
write-host "--------------------------"
write-host "Script Info" -foreground Green
write-host "--------------------------"
write-host
write-host " Script Name : Exchange 2010 Dashboard Script" -foreground Cyan
write-host " Author
: Ammar Hasayen based on Steve Goodman's Exchange
Environemnt Report" -foreground Cyan
write-host " Version
: 1.0" -foreground Cyan
write-host
write-host "--------------------------"
write-host "Script Release Notes" -foreground Green
write-host "--------------------------"
write-host
write-host " - The script assumes you have only Exchange 2010 environment.
Script also assumes you have any type of DAG deployment."
write-host " - You must run the script with an account that has admin rights
on all Exchange Servers to collect disk and O.S health info."
write-host " - Also, the account should have access to read all Exchange
Information (ViewAdministrator)."
write-host " - Script should be able to connect to all Exchange servers using
WMI."
write-host " - Script needs (Microsoft Chart Controls for Microsoft .NET
Framework) to be installed only on the machine that will run the script. This
is needed in order to generate charts."
write-host " - Download here : Microsoft Chart Controls for Microsoft .NET
Framework 3.5 (http://www.microsoft.com/en-us/download/details.aspx?id=14422).
"
write-host " - Script may take some time to run, depending on your environment
size."
Write-host
write-host " - Don't Worry :) The script WILL NOT perform any change or SET
operations in your environment...It will only use GET and read operations." foreground Yellow
write-host " - ALWAYS CHECK FOR NEWER VERSION @
http://ammarhasayen.wordpress.com. Search for Dashboard." -foreground Yellow
write-host
sleep 2
write-host "--------------------------"
write-host "Script Start" -foreground Green
write-host "--------------------------"
Write-Host
write-host " 1.Creating Files" -foreground "magenta"
# This is the HTMl document that will host the Dashboard
New-Item `
-ItemType file `
-Path "F:\ScheduledScripts\Pilot" `
-Name DashboardV1.htm `
-Force
$filename1 = "F:\ScheduledScripts\Pilot\DashboardV1.htm"
#----------------------------------# Section 2 - Script Functions
#----------------------------------# <<<<< Function: Send Email >>>>>
Function sendEmail
{
param($from,$to,$subject,$smtphost,$htmlFileName)
$chart1=
$chart2=
$chart3=
$chart4=
"F:\ScheduledScripts\Pilot\Mailboxes Vs Servers.JPEG"
"F:\ScheduledScripts\Pilot\Database size.JPEG"
"F:\ScheduledScripts\Pilot\Database Vs Mailboxes.JPEG"
"F:\ScheduledScripts\Pilot\Database Backup.JPEG"
[Array]$DAGAttachments = @()
foreach ($DAG in $ExchangeEnvironment.DAGS)
{
$DAGAttachments += "F:\ScheduledScripts\Pilot\$($DAG.Name) - DBs
Per server.JPEG"
}
$att1
$att2
$att3
$att4
=
=
=
=
new-object
new-object
new-object
new-object
Net.Mail.Attachment($chart1)
Net.Mail.Attachment($chart2)
Net.Mail.Attachment($chart3)
Net.Mail.Attachment($chart4)
$msg = new-object Net.Mail.MailMessage
$msg.From = $from
$msg.To.Add($to)
$msg.Subject = $subject
$msg.Body = Get-Content $htmlFileName
$msg.isBodyhtml = $true
$msg.Attachments.Add($att1)
$msg.Attachments.Add($att2)
$msg.Attachments.Add($att3)
$msg.Attachments.Add($att4)
foreach ($item in $DAGAttachments)
{
$attachment = new-object Net.Mail.Attachment($item)
$msg.Attachments.Add($attachment)
}
$smtp = new-object Net.Mail.SmtpClient($smtphost)
$smtp.Send($msg)
$att1.Dispose()
$att2.Dispose()
$att3.Dispose()
$att4.Dispose()
foreach ($item in $DAGAttachments)
{
$attachment = new-object Net.Mail.Attachment($item)
$attachment.Dispose()
}
}
# <<<<< Function: Gather DB Layout Info >>>>>>
function _GetDAG_DB_Layout
{
param($Databases,$DAG)
$WarningColor
$ErrorColor
$BGColHeader
$BGColSubHeader
[Array]$Servers_In_DAG
= "#FF9900"
= "#980000"
= "#000099"
= "#0000FF"
= $DAG.Members
$HTML_Output_File ="<table border=""0"" cellpadding=""3"" width=""50%""
style=""font-size:8pt;font-family:Arial,sans-serif"">
<col width=""5%"">
<colgroup width=""25%"">"
$Servers_In_DAG | Sort-Object| % { $HTML_Output_File+="<col
width=""3%"">"}
$HTML_Output_File +="</colgroup>"
$ServerCount
= $Servers_In_DAG.Count
$HTML_Output_File += "<tr bgcolor=""$($BGColHeader)""><th><font
color=""#ffffff"">DatabaseCopies</font></th>
<th colspan=""$($ServerCount)""><font color=""#ffffff"">Mailbox
Servers in $($DAG.name)</font></th>
</tr>"
$HTML_Output_File+="<tr bgcolor=""$($BGColSubHeader)""><th></th>"
$Servers_In_DAG|Sort-Object | %{$HTML_Output_File+="<th><font
color=""#ffffff"">$($_)</font></th>"}
$HTML_Output_File += "</tr>"
#writing table content
$AlternateRow=0
foreach ($Database in $Databases)
{
$HTML_Output_File+="<tr "
if ($AlternateRow)
{
$HTML_Output_File+="
style=""background-color:#dddddd"""
$AlternateRow=0
}
else
{
$AlternateRow=1
}
$HTML_Output_File+="><td><strong>$($database.name)</strong></td>"
#copies
$DatabaseServer
= $Database.ActiveOwner
$DatabaseServers
= $Database.DBHolders
$Servers_In_DAG|Sort-Object|
%{
$ActvPref
=$Database.DB_Act_pref
$server_in_the_loop = $_
$Actv = $ActvPref
|where {$_.key -eq
$server_in_the_loop}
$Actv=
$Actv.value
$ActvKey=
$ActvPref |Where {$_.value -eq 1}
$ActvKey =
$ActvKey.key.name
$HTML_Output_File+="<td"
if (
contains $_) -and ( $_ -like $databaseserver)
($DatabaseServers -
)
{
if (
$ActvKey -like $databaseserver
)
{$HTML_Output_File+=" align=""center"" style=""backgroundcolor:#F7FB0B""><font color=""#000000f""><strong>$Actv</strong></font> "}
else
{$HTML_Output_File+=" align=""center"" style=""backgroundcolor:#FB0B1B""><strong><font color=""#ffffff"">$Actv</strong</font> "}
}
elseif
($DatabaseServers -contains $_)
{
$HTML_Output_File+=" align=""center"" style=""backgroundcolor:#00FF00"">$Actv "
}
else
{ $HTML_Output_File+="
align=""center"" style=""background-color:#dddddd"">" }
}
$HTML_Output_File+="</tr >"
}
$HTML_Output_File+="<tr></tr><tr></tr><tr></tr>"
#Total Assigned copies
$HTML_Output_File += "<tr bgcolor=""#440164""><th><font
color=""#ffffff"">Total Copies</font></th>"
$Servers_In_DAG|Sort-Object|
%{
$this =
$ExchangeEnvironment.Servers[$_]
$HTML_Output_File
+= "<td align=""center"" style=""background-color:#E0ACF8""><font
color=""#000000""><strong>$($this.DBCopyCount)</strong></font>"
}
$HTML_Output_File +="</tr>"
#Copies Assigned Ideal
$HTML_Output_File += "<tr bgcolor=""#DB08CD""><th><font
color=""#ffffff"">Ideal Mounted DB Copies</font></th>"
$Servers_In_DAG|Sort-Object|
%{
foreach ($this in $My_Hash_3.GetEnumerator())
{
if ($this.key like $_)
{$HTML_Output_File
+= "<td align=""center"" style=""background-color:#FBCCF9""><font
color=""#000000""><strong>$($this.value)</strong></font>"}
}
}
$HTML_Output_File +="</tr>"
# Copies Actually Assigned
$HTML_Output_File += "<tr bgcolor=""#440164""><th><font
color=""#ffffff"">Actual Mounted DB Copies</font></th>"
$Servers_In_DAG|Sort-Object|
%{
$this =
$ExchangeEnvironment.Servers[$_]
$HTML_Output_File
+= "<td align=""center"" style=""background-color:#E0ACF8""><font
color=""#000000""><strong>$($this.DBCopyCount_Assigned)</strong></font>"
}
$HTML_Output_File +="</tr>"
$HTML_Output_File
}
# <<<<< Function: Recovery Databases Info >>>>>>
function _GetRecoveryDBTable
{
param($Databases)
# Drawing Table header
$Output="<table border=""0"" cellpadding=""3"" width=""100%""
style=""font-size:8pt;font-family:Arial,sans-serif"">
<tr align=""center"" bgcolor=""#FFD700"">"
$Output+="<th>#</th><th>Database
Name</th><th>Mounted</th><th>Server</th>"
$Output+="<th>DB Size</th>"
$Output+="<th>DB Disk Free</th>"
$Output+="<th>Log Disk Free</th>"
$Output+="</tr>"
$AlternateRow=0;
#Writing Table content
foreach ($Database in $Databases)
{
$C++
$Output+="<tr"
if ($AlternateRow)
{
$Output+=" style=""background-color:#dddddd"""
$AlternateRow=0
} else
{
$AlternateRow=1
}
$Output+=">"
$Output+="<td align=""center""><strong>$C</strong></td>"
$Output+="<td
align=""center""><strong>$($Database.Name)</strong></td>"
If($Database.Mounted -eq $True)
{$Output+="<td align=""center""><font
color=""#008000""><Strong>$($Database.Mounted)</Strong></font></td>"
$Output+="<td align=""center""><font
color=""#000000"">$($Database.ActiveOwner)</font></td>"
$Output+="<td align=""center"">$("{0:N2}" -f ($Database.Size/1GB))
GB </td>"}
else
{$Output+="<td align=""center""><font
color=""#000000""><Strong>$($Database.Mounted)</Strong></font></td>"
$Output+="<td align=""center""><font
color=""#00000"">$($Database.ActiveOwner)</font></td>"
$Output+="<td align=""center""> -</td>" }
$Output+="<td align=""center"">$("{0:N1}" -f
$Database.FreeDatabaseDiskSpace)%</td>"
$Output+="<td align=""center"">$("{0:N1}" -f
$Database.FreeLogDiskSpace)%</td>"
$Output+="</tr>";
}
$Output+="</table><br />"
$Output
}
# <<<<< Function: Gather DB Info >>>>>>
# Sub Function to return HTML Table for Databases
function _GetDBTable
{
param($Databases)
# Only Show Archive Mailbox Columns, Backup Columns and Circular Logging
if at least one DB has an Archive mailbox, backed up or Circular Log enabled.
$ShowArchiveDBs
= $False
$ShowLastFullBackup
= $False
$ShowCircularLogging
= $False
$ShowCopies=$False
$ShowFreeDatabaseSpace
= $False
$ShowFreeLogDiskSpace
= $False
$WarningColor
= "#FF9900"
$ErrorColor
="#980000"
[int]$BackupNow
= 0
[int]$C
= 0
foreach ($Database in $Databases)
{
if ($Database.ArchiveMailboxCount -gt 0)
{
$ShowArchiveDBs=$True
}
if ($Database.LastBackup -ne "?")
{
$ShowLastFullBackup=$True
}
if ($Database.CircularLoggingEnabled -eq "Yes")
{
$ShowCircularLogging=$True
}
if ($Database.CopyCount -gt 0)
{
$ShowCopies=$True
}
if ($Database.FreeDatabaseDiskSpace -ne $null)
{
$ShowFreeDatabaseSpace=$true
}
if ($Database.FreeLogDiskSpace -ne $null)
{
$ShowFreeLogDiskSpace=$true
}
}
# Drawing Table header
$Output="<table border=""0"" cellpadding=""3"" width=""100%""
style=""font-size:8pt;font-family:Arial,sans-serif"">
<tr align=""center"" bgcolor=""#FFD700"">"
$Output+="<th>#</th><th>Database
Name</th><th>Mounted</th><th>Mailboxes</th><th>Av. Mailbox Size</th>"
if ($ShowArchiveDBs)
{
$Output+="<th>Archives</th><th>Av. Archive Size</th>"
}
$Output+="<th>DB Size</th><th>DB Whitespace</th>"
if ($ShowCircularLogging)
{
$Output+="<th>Circular Logging</th>"
}
$Output+="<th>Dumps.WQ</th>"
$Output+="<th>Dumps.Q</th>"
$Output+="<th>DB PS (G)</th>"
$Output+="<th>DB PSR (G)</th>"
$Output+="<th>Copies</th><th>Server</th>"
if ($ShowFreeDatabaseSpace)
{
$Output+="<th>Database Disk Free</th>"
}
if ($ShowFreeLogDiskSpace)
{
$Output+="<th>Log Disk Free</th>"
}
$Output+="<th><strong>Act Pref.</strong></th>"
$Output+="<th><strong>Index H</strong></th>"
$Output+="<th><strong>DB Access</strong></th>"
if ($ShowLastFullBackup)
{
$Output+="<th>Last Full Backup</th><th>Since?</th>"
}
$Output+="</tr>"
$AlternateRow=0;
#Writing Table content
foreach ($Database in $Databases)
{
$C++
$Output+="<tr"
if ($AlternateRow)
{
$Output+=" style=""background-color:#dddddd"""
$AlternateRow=0
} else
{
$AlternateRow=1
}
$Output+=">"
$Output+="<td align=""center""><strong>$C</strong></td>"
$Output+="<td
align=""center""><strong>$($Database.Name)</strong></td>"
If($Database.Mounted -eq $True)
{$Output+="<td align=""center""><font
color=""#008000""><Strong>$($Database.Mounted)</Strong></font></td>"}
else
{$Output+=" <td align=""center"" style=""backgroundcolor:$($ErrorColor)"">"}
if( ($Database.MailboxCount) -lt $MailboxCountThreshold)
{$Output+="<td align=""center"">$($Database.MailboxCount)</td>"}
else
{$Output+="<td align=""center"" style=""backgroundcolor:$($ErrorColor)""><font
color=""#ffffff""><strong>$($Database.MailboxCount)</strong></font></td>"}
$Output+="<td align=""center"">$("{0:N2}" -f
($Database.MailboxAverageSize/1MB)) MB</td>"
if ($ShowArchiveDBs)
{
$Output+="<td
align=""center"">$($Database.ArchiveMailboxCount)</td>
<td align=""center"">$("{0:N2}" -f
($Database.ArchiveAverageSize/1MB)) MB</td>";
}
$Size=$Database.Size/1GB
if($Size -lt $DBSizeThreshold)
{$Output+="<td align=""center"">$("{0:N2}" -f
($Database.Size/1GB)) GB </td>"}
else
{$Output+="<td align=""center"" style=""backgroundcolor:$($ErrorColor)""><font color=""#ffffff""><strong>$("{0:N2}" -f
($Database.Size/1GB)) GB</strong></font></td>"}
$Output+="<td align=""center"">$("{0:N2}" -f
($Database.Whitespace/1GB)) GB</td>"
if ($ShowCircularLogging)
{
$Output+="<td
align=""center"">$($Database.CircularLoggingEnabled)</td>"
}
$Output+="<td
align=""center"">$($Database.DatabaseDumpsterWQ)</td>";
$Output+="<td
align=""center"">$($Database.DatabaseDumpsterq)</td>";
$Output+="<td align=""center"">$($Database.DatabasePS)</td>";
$Output+="<td align=""center"">$($Database.DatabasePSR)</td>";
$Output+="<td
align=""center"">$($Database.CopyCount)</td><td>$($Database.ActiveOwner)</td>";
if ($ShowFreeDatabaseSpace)
{
if ( $Database.FreeDatabaseDiskSpace -gt
$DiskSpaceThreshold)
{$Output+="<td align=""center"">$("{0:N1}" -f
$Database.FreeDatabaseDiskSpace)%</td>"}
else
{$Output+="<td align=""center"" style=""backgroundcolor:$($ErrorColor)""><font color=""#ffffff""><strong>$("{0:N1}" -f
$Database.FreeDatabaseDiskSpace)%</strong></font></td>"}
}
if ($ShowFreeLogDiskSpace)
{
if ( $Database.FreeLogDiskSpace -gt $DiskSpaceThreshold)
{$Output+="<td align=""center"">$("{0:N1}" -f
$Database.FreeLogDiskSpace)%</td>"}
else
{$Output+="<td align=""center"" style=""backgroundcolor:$($ErrorColor)""><font color=""#ffffff""><strong>$("{0:N1}" -f
$Database.FreeLogDiskSpace)%</strong></font></td>"}
}
if ($Database.DBPreCheck -like "Pass")
{$Output+="<td
align=""center""><strong>$($Database.DBPreCheck)</strong></td>"}
else {$Output+="<td align=""center"" style=""backgroundcolor:$($WarningColor)""></td>"}
if ( $Database.IndexHealth -like "Pass")
{$Output+="<td
align=""center""><strong>$($Database.IndexHealth)</strong></td>"}
else
{$Output+="<td align=""center"" style=""backgroundcolor:$($WarningColor)""></td>"}
if ( $Database.Databasemapi -like "Pass")
{$Output+="<td
align=""center""><strong>$($Database.Databasemapi)</strong></td>"}
else
{$Output+="<td align=""center"" style=""backgroundcolor:$($ErrorColor)""></td>"}
$ErrorColor ="#FF00FF"
if ($ShowLastFullBackup)
{
$Output+="<td
align=""center"">$($Database.LastBackup)</td>"
if ( ($Database.HowOldBackup) -ge $BackupError)
{$Output+="<td align=""center"" style=""backgroundcolor:$($ErrorColor)""><font
color=""#ffffff""><strong>$($Database.HowOldBackup)</strong></font></td>"}
elseif ( ($Database.HowOldBackup) -ge $BackupWarning)
{$Output+="<td align=""center"" style=""backgroundcolor:$($WarningColor)""><font
color=""#ffffff""><strong>$($Database.HowOldBackup)</strong></font></td>"}
elseif ( ($Database.HowOldBackup) -eq $BackupNow)
{$Output+="<td align=""center"" style=""backgroundcolor:#008000""><font
color=""#ffffff""><strong>$($Database.HowOldBackup)</strong></font></td>"}
elseif ( ($Database.HowOldBackup) -eq "?")
{$Output+="<td align=""center"" style=""backgroundcolor:#F7FE2E""><strong>$($Database.HowOldBackup)</strong></td>"}
else {$Output+="<td
align=""center"">$($Database.HowOldBackup)</td>"}
}
$Output+="</tr>";
$ErrorColor ="#980000"
}
$Output+="</table><br />"
$Output
}
# <<<<< Function: Organization Information >>>>>>
function _GetOverview
{
param($Servers,$ExchangeEnvironment,$ExRoleStrings)
$WarningColor
= "#FF9900"
$ErrorColor
= "#980000"
$BGColHeader
= "#000099"
$BGColSubHeader
= "#0000FF"
$Prefix
= "Site:"
$Output ="<table border=""0"" cellpadding=""3"" width=""100%""
style=""font-size:8pt;font-family:Arial,sans-serif"">
<col width=""7%""><col width=""7%"">
<colgroup width=""25%"">";
$ExchangeEnvironment.TotalServersByRole.GetEnumerator()|Sort Name|
%{$Output+="<col width=""3%"">"}
$Output+="</colgroup><col width=""7%""><col width=""3%""><col
width=""5%"">
<colgroup width=""6""><col width=""3%""><col width=""3%""></colgroup>
<col width=""5%""><col width=""5%""><col width=""5%"">
<colgroup width=""25""><col width=""4%""><col width=""4%""><col
width=""4%""><col width=""4%""><col width=""4%""><col width=""4%""></colgroup>
<col width=""5%"">
<tr bgcolor=""$($BGColHeader)""><th><font color=""#ffffff"">$($Prefix)
$($Servers.Key)</font></th>
<th><font color=""#ffffff"">Exchange Version</font></th>
<th colspan=""$($ExchangeEnvironment.TotalServersByRole.Count)""><font
color=""#ffffff"">Roles Installed</font></th>
<th><font color=""#ffffff"">OS Version</font></th>
<th><font color=""#ffffff"">OS SP</font></th>
<th><font color=""#ffffff"">Ping</font></th>
<th colspan=""2""><font color=""#ffffff"">Disk</font></th>
<th><font color=""#ffffff"">UpTime</font></th>
<th><font color=""#ffffff"">Services</font></th>
<th><font color=""#ffffff""> DBs </font></th>
<th colspan=""6""><font color=""#ffffff"">Databases Status</font></th>
<th><font color=""#ffffff"">MRS</font></th>
</tr>"
$TotalMailboxes = 0
$Servers.Value | %{$TotalMailboxes += $_.MailboxesCount}
$Output+="<tr bgcolor=""$($BGColSubHeader)""><th><font
color=""#ffffff"">Mailboxes: $($TotalMailboxes)</font></th><th></th>"
$ExchangeEnvironment.TotalServersByRole.GetEnumerator()|Sort Name|
%{$Output+="<th><font
color=""#ffffff"">$($ExRoleStrings[$_.Key].Short)</font></th>"}
$Output+="<th></th><th></th><th></th>
<th><font color=""#ffffff"">System</font></th>
<th><font color=""#ffffff"">Data</font></th>
<th></th><th></th><th></th>
<th><font color=""#ffffff"">Status</font></th>
<th><font color=""#ffffff"">Index</font></th>
<th><font color=""#ffffff"">CopyQ</font></th>
<th><font color=""#ffffff"">ReplayQ</font></th>
<th><font color=""#ffffff"">MailFlow</font></th>
<th><font color=""#ffffff"">Repl.</font></th>
<th></th>
</tr>"
$AlternateRow=0
foreach ($Server in $Servers.Value)
{
$Output+="<tr "
if ($AlternateRow)
{
$Output+=" style=""backgroundcolor:#dddddd"""
$AlternateRow=0
} else
{
$AlternateRow=1
}
# Server name and Exch version
$Output+="><td>$($Server.Name)"
$Output+="</td>
<td>$($ExVersionStrings["$($Server.ExchangeMajorVersion).$($Server.Exchan
geSPLevel)"].Long)"
if ($Server.RollupLevel -gt 0)
{
$Output+=" UR$($Server.RollupLevel)"
if
($Server.RollupVersion)
{
$Output+=" $($Server.RollupVersion)"
}
}
$Output+="</td>"
#Roles
$ExchangeEnvironment.TotalServersByRole.GetEnumerator()|Sort Name|
%{
$Output+="<td"
if ($Server.Roles contains $_.Key)
{
$Output+=" align=""center"" style=""background-color:#00FF00"""
}
$Output+=">"
if (( $_.Key -eq
"Mailbox") -and $Server.Roles -contains $_.Key)
{
$Output+=$Server.MailboxesCount
}
}
# O.S Version and SP LEvel
$Output+="<td>$($Server.OSVersion)</td><td>$($Server.OSServicePack)</td>"
;
# Ping
if ($Server.SvrConnection -eq $true)
{
$Output+="<td align=""center"">Pass</td>"
}
else
{
$Output+="<td align=""center"" style=""backgroundcolor:$($ErrorColor)""></td>"
}
# Disk System Drive
if ($Server.SystemDriveHealth -like "Good")
{
$Output+="<td align=""center"">Pass"
}
elseif ($Server.SystemDriveHealth -like "Warning")
{
$Output+="<td align=""center"" style=""backgroundcolor:$($WarningColor)"">"
}
elseif ($Server.SystemDriveHealth -like "Error")
{
$Output+="<td align=""center"" style=""backgroundcolor:$($ErrorColor)"">"
}
else {
$Output+="<td align=""center"">?"
}
# Disks - Data Drives
if ($Server.DataDriveHealth -like "Good")
{
$Output+="<td align=""center"">Pass"
}
elseif ($Server.DataDriveHealth -like "Warning")
{
$Output+="<td align=""center"" style=""backgroundcolor:$($WarningColor)"">$($Server.C_DataDrive_W)"
}
elseif ($Server.DataDriveHealth -like "Error")
{
$Output+="<td align=""center"" style=""backgroundcolor:$($ErrorColor)""><font
color='#FFFFFF'><Strong>$($Server.C_DataDrive_E)</strong></font>"
}
elseif ($Server.DataDriveHealth -like "No")
{$Output+="<td align=""center"">N/A"
}
else {
$Output+="<td align=""center"">?"
}
# UPtime
if ($Server.UpTime -like "Server Down")
{$Output+="<td align=""center"">?"
}
elseif ($Server.UpTime -le $UptimeWarningThreshold)
{
$Output+="<td align=""center"">$($Server.UpTime)</td>"
}
elseif ($Server.UpTime -le $UptimeErrorThreshold)
{
$Output+="<td align=""center"" style=""backgroundcolor:$($WarningColor)""><Strong>$($Server.UpTime)</Strong></td>"
}
else
{
$Output+="<td align=""center"" style=""backgroundcolor:$($ErrorColor)""><Strong>$($Server.UpTime)</Strong></td>"
}
# Services
if ($Server.ServiceHealth -like "Pass")
{
$Output+="<td align=""center"">Pass</td>"
}
elseif ($Server.ServiceHealth -like "Fail")
{
$Output+="<td align=""center"" style=""backgroundcolor:$($ErrorColor)""><font
color='#FFFFFF'><Strong>$($Server.ServiceHealthDownCount)</strong></font></td>"
}
else
{$Output+="<td align=""center"">?"}
#DBs Count
if (!($Server.Roles -contains "Mailbox") )
{$Output+="<td align=""center"">N/A</td>"}
elseif($Server.DBCopyCount -eq 1000)
{$Output+="<td align=""center"">0/0</td>"}
elseif ($Server.DBCopyCount_Assigned -gt $DBCountThreshold)
{$Output+="<td
align=""center"">$($Server.DBCopyCount_Assigned)/$($Server.DBCopyCount)</td>"
}
else{ $Output+="<td align=""center"" style=""backgroundcolor:$($Warning)"">$($Server.DBCopyCount_Assigned)/$($Server.DBCopyCount)</td>
"
}
# DB Status
if (!($Server.Roles -contains "Mailbox") )
{$Output+="<td align=""center"">N/A</td>"}
elseif($Server.DBCopyCount -eq 1000)
{$Output+="<td align=""center"">N/A</td>"}
elseif ($Server.dbcopy_status_H -like "Pass")
{$Output+="<td align=""center"">Pass"}
elseif ($Server.dbcopy_status_H -like "Fail")
{$Output+="<td align=""center"" style=""backgroundcolor:$($ErrorColor)""><font
color='#FFFFFF'><Strong>$($Server.DBCopyCount_NotGood)</strong></font>"
else
{$Output+="<td align=""center"">?"}
# DB Index
if (!($Server.Roles -contains "Mailbox") )
{$Output+="<td align=""center"">N/A</td>"}
elseif($Server.DBCopyCount -eq 1000)
}
{$Output+="<td align=""center"">N/A</td>"}
elseif ($Server.dbcopy_ContentIndexState_H -like "Pass")
{
$Output+="<td align=""center"">Pass"}
elseif ($Server.dbcopy_ContentIndexState_H -like "Fail")
{$Output+="<td align=""center"" style=""backgroundcolor:$($WarningColor)"">" }
else
{$Output+="<td align=""center"">?"}
# DB CopyQ
if (!($Server.Roles -contains "Mailbox") )
{$Output+="<td align=""center"">N/A</td>"}
elseif($Server.DBCopyCount -eq 1000)
{$Output+="<td align=""center"">N/A</td>"}
elseif ($Server.dbcopy_CopyQueueLength_H -like "Pass")
{$Output+="<td align=""center"">Pass"}
elseif ($Server.dbcopy_CopyQueueLength_H -like "Fail")
{$Output+="<td align=""center"" style=""backgroundcolor:$($WarningColor)"">"}
else{$Output+="<td align=""center"">?"}
# DB ReplayQ
if (!($Server.Roles -contains "Mailbox") )
{$Output+="<td align=""center"">N/A</td>"}
elseif($Server.DBCopyCount -eq 1000)
{$Output+="<td align=""center"">N/A</td>"}
elseif ($Server.dbcopy_ReplayQueueLength_H -like "Pass")
{$Output+="<td align=""center"">Pass"}
elseif ($Server.dbcopy_ReplayQueueLength_H -like "Fail")
{$Output+="<td align=""center"" style=""backgroundcolor:$($WarningColor)"">" }
else
{$Output+="<td align=""center"">?"}
# DB Mail FLow
if (!($Server.Roles -contains "Mailbox") )
{$Output+="<td align=""center"">N/A</td>"}
elseif($Server.DBCopyCount -eq 1000)
{$Output+="<td align=""center"">N/A</td>"}
elseif ($Server.MailboxServerTestMailFlow -like "Pass")
{$Output+="<td align=""center"">Pass"}
elseif ($Server.MailboxServerTestMailFlow -like "Fail")
{$Output+="<td align=""center"" style=""backgroundcolor:$($WarningColor)"">" }
else
{$Output+="<td align=""center"">?"}
# DB Replication Services
if (!($Server.Roles -contains "Mailbox") )
{$Output+="<td align=""center"">N/A</td>"}
elseif ($Server.ReplHealth -like "Pass")
{$Output+="<td align=""center"">Pass"}
elseif ($Server.ReplHealth -like "Fail")
{$Output+="<td align=""center"" style=""backgroundcolor:$($WarningColor)"">"}
else
{$Output+="<td align=""center"">?"}
# CAS MRS
if (!($Server.Roles -contains "ClientAccess") )
{$Output+="<td align=""center"">N/A</td>"}
elseif ($Server.MRS_Health -like "Pass")
{
$Output+="<td align=""center"">Pass</td>"}
elseif ($Server.MRS_Health -like "Fail")
{$Output+="<td align=""center"" style=""backgroundcolor:$($ErrorColor)""></td>"}
else
{$Output+="<td align=""center"">?</td>"}
#CLose the table
$Output+= "</tr>"
} # End of ForEach $Server in that Site
$Output+="<tr></tr>
</table><br />"
$Output
}
# <<<<< Function: Test Database Search Index >>>>>>
funCtion _TestSearchDBIndex ($Database)
{
$DB_Search_Test = (Test-ExchangeSearch -MailboxDatabase $Database IndexingTimeoutInSeconds 30 -ErrorAction SilentlyContinue)
if ($DB_Search_Test)
{
$Get_DB_Search_Test_ResultFound = $DB_Search_Test.ResultFound
$Get_DB_Search_Test_ERROR
= $DB_Search_Test.ERROR
if ( ($Get_DB_Search_Test_ResultFound -eq $true) -and
($Get_DB_Search_Test_ERROR -eq $null) )
{$DB_Search_Test_Status = "Pass"}
else
{$DB_Search_Test_Status = "Fail"}
}
else {$DB_Search_Test_Status = "N/A"}
$DB_Search_Test_Status
}
# <<<<< Function: Database Info >>>>>>
function _GetDB
{
param($Database,$ExchangeEnvironment,$Mailboxes,$ArchiveMailboxes)
# Mount Status
$Mounted = $Database.Mounted
# Circular Logging, Last Full Backup
if ($Database.CircularLoggingEnabled) { $CircularLoggingEnabled="Yes" }
else { $CircularLoggingEnabled = "No" }
# Mailbox Average Sizes
$MailboxStatistics =
[array]($ExchangeEnvironment.Servers[$Database.Server.Name].MailboxStatistics |
Where {$_.Database -eq $Database.Identity})
if ($MailboxStatistics)
{
[long]$MailboxItemSizeB = 0
$MailboxStatistics | %{ $MailboxItemSizeB+=$_.TotalItemSizeB }
[long]$MailboxAverageSize = $MailboxItemSizeB /
$MailboxStatistics.Count
} else {
$MailboxAverageSize = 0
}
# Free Disk Space Percentage
if ($ExchangeEnvironment.Servers[$Database.Server.Name].Disks)
{
foreach ($Disk in
$ExchangeEnvironment.Servers[$Database.Server.Name].Disks)
{
if ($Database.EdbFilePath.PathName -like "$($Disk.Name)*")
{
$FreeDatabaseDiskSpace = $Disk.FreeSpace /
$Disk.Capacity * 100
}
if ($Database.LogFolderPath.PathName -like
"$($Disk.Name)*")
{
$FreeLogDiskSpace = $Disk.FreeSpace /
$Disk.Capacity * 100
}
}
} else {
$FreeLogDiskSpace
= $null
$FreeDatabaseDiskSpace = $null
}
#Activation Preference List
$DB_Act_pref = $Database.ActivationPreference
# DB Tests if the DB is mounted
if ($Mounted)
{
$ActiveSrv = $Database.Server.Name
$ActiveSrvConn =
(($ExchangeEnvironment.Servers["$ActiveSrv"] ).SvrConnection)
if ( $ActiveSrvConn -eq $True )
{
#Index Health
$IndexHealth = _TestSearchDBIndex $Database
# Mapi Test
$mapistatus = Test-MapiConnectivity `
-Database $Database `
-PerConnectionTimeout 10
$Get_mapistatus_Result_Value = $mapistatus.Result.Value
if ($Get_mapistatus_Result_Value
{$Databasemapi = "fail"}
else
{$Databasemapi = "Pass" }
-ne "Success")
}
else # Server not reachable
{
$IndexHealth = "N/A"
$Databasemapi = "N/A"
}
}
else # if the DB is not mounted
{
$IndexHealth = "N/A"
$Databasemapi = "N/A"
}
# Check Activation Preference
$DatabasePereferenceServer = $Database.ACTIVATIONPREFERENCE |Where
{$_.value -eq 1}
$DatabasePereference =$DatabasePereferenceServer.key.name
$DatabaseNOWSRV = $Database.Server.name
If ( $DatabasePereference -ne $DatabaseNOWSRV )
{$DatabasePreCheck = "Fail"}
else
{$DatabasePreCheck = "Pass"}
# Checking backup
$lastBackup = $Database.LastFullBackup
if($lastBackup)
{
$currentDate = Get-Date
if ($lastBackup -eq $null)
{
$HowOldBackup= $null
}
else
{
$HowOldBackup= $currentDate - $lastBackup
$HowOldBackup= $HowOldBackup.days
}
}
else
{
$lastBackup = "?"
$HowOldBackup="?"
}
# DB Quota Info
$Get_DB_ProhibitSendReceiveQuota_isunlimited =
$Database.ProhibitSendReceiveQuota.isunlimited
$Get_DB_ProhibitSendQuota_isunlimited
=
$Database.ProhibitSendQuota.isunlimited
if ($Get_DB_ProhibitSendReceiveQuota_isunlimited -eq $true)
{$DatabasePSR = "Unlimited"}
else
{$DatabasePSR = ($Database.ProhibitSendReceiveQuota.Value.ToMB() )
/1024}
if ($Get_DB_ProhibitSendQuota_isunlimited -eq $TRUE )
{$DatabasePS = "Unlimited"}
else
{$DatabasePS = ($Database.ProhibitSendQuota.Value.ToMB() ) /1024}
# DB Dumpster Info
$DatabaseDumpsterWQ =
($Database.RecoverableItemsWarningQuota.Value.ToMB() )
$DatabaseDumpsterQ = ($Database.RecoverableItemsQuota.Value.ToMB() )
/1024
# Copy Count
$CopyCount = [int]$Database.Servers.Count
if ($Database.MasterServerOrAvailabilityGroup.Name -ne
$Database.Server.Name)
{
$Copies = [array]($Database.Servers | % { $_.Name })
} else {
$Copies = @()
}
# Archive Info
$ArchiveMailboxCount = [int]([array]($ArchiveMailboxes | Where
{$_.ArchiveDatabase -eq $Database.Name})).Count
$ArchiveStatistics = [array]($ArchiveMailboxes | Where
{$_.ArchiveDatabase -eq $Database.Name} | Get-MailboxStatistics -Archive )
if ($ArchiveStatistics)
{
[long]$ArchiveItemSizeB = 0
$ArchiveStatistics | %{
$ArchiveItemSizeB+=$_.TotalItemSize.Value.ToBytes() }
[long]$ArchiveAverageSize = $ArchiveItemSizeB /
$ArchiveStatistics.Count
} else {
$ArchiveAverageSize = 0
}
# DB Size / Whitespace Info
Try{[long]$Size = $Database.DatabaseSize.ToBytes()}Catch{}
Try{[long]$Whitespace =
$Database.AvailableNewMailboxSpace.ToBytes()}Catch{}
# DAG Memebersheip
$DatabaseDagMembershipValue =
$Database.MasterServerOrAvailabilityGroup.name
if ($DatabaseDagMembershipValue -match "DAG")
{$DatabaseDagMembership = $DatabaseDagMembershipValue }
else
{$DatabaseDagMembership = "N/A" }
#Get DB Servers
[array]$DBHolders =$null
( $Database.Servers) |%{$DBHolders
+= $_.name}
@{Name
= $Database.Name
ActiveOwner
= $Database.Server.Name.ToUpper()
MailboxCount
= [long]([array]($Mailboxes |
Where {$_.Database -eq $Database.Identity})).Count
MailboxAverageSize
= $MailboxAverageSize
ArchiveMailboxCount
= $ArchiveMailboxCount
ArchiveTotalSize
= $ArchiveItemSizeB
ArchiveAverageSize
= $ArchiveAverageSize
CircularLoggingEnabled
= $CircularLoggingEnabled
Size
= $Size
Whitespace
= $Whitespace
Copies
= $Copies
CopyCount
= $CopyCount
FreeLogDiskSpace
= $FreeLogDiskSpace
FreeDatabaseDiskSpace
= $FreeDatabaseDiskSpace
DBPreCheck
= $DatabasePreCheck
lastBackup
= $lastBackup
HowOldBackup
= $HowOldBackup
DBDagMembership
= $DatabaseDagMembership
IndexHealth
= $IndexHealth
Databasemapi
= $Databasemapi
DatabaseDumpsterWQ
= $DatabaseDumpsterWQ
DatabaseDumpsterQ
= $DatabaseDumpsterQ
DatabasePS
= $DatabasePS
DatabasePSR
= $DatabasePSR
DatabaseDagMembership
= $DatabaseDagMembership
Mounted
= $Mounted
DBHolders
= $DBHolders
DB_Act_pref
= $DB_Act_pref
DatabasePereferredServer = $DatabasePereference
IsRecovery
= $Database.Recovery
}
}
# <<<<< Function: Disk Information >>>>>>
function _GetDiskInfo
{
param($Server)
#Getting raw data
$tWMI =Get-WMIObject Win32_LogicalDisk `
-ComputerName $Server `
-ErrorAction SilentlyContinue |
Where-Object {$_.DriveType -eq 3}
#Formating the data into array
$DiskTable =$tWMI |
select Name ,@{n='Size (Gb)' ;e={"{0:n2}" -f
($_.size/1gb)}},@{n='FreeSpace';e={"{0:n2}" -f ($_.freespace/1gb)}},
@{n='PercentFree';e={"{0:n2}" -f ($_.freespace/$_.size*100)}} |
Sort-Object -Property Name
#Return array
$DiskTable
} #Function Ends
# <<<<< Function: Disk Health >>>>>>
function _GetExchDiskHealth
{
param ($DiskTable, $Roles ,$name)
# $Disk Table is an array that we take from the _Get-DiskInfo
function
# Disk Table contains the following properties :
# Name
# Size
# FreeSpace
# PercentFree
# $Roles is a string array that list the roles that Exchange holds
# According to the role, we will define different disk threshoulds
# Variables
$C_DataDrive
$C_DataDrive_G
$C_DataDrive_W
$C_DataDrive_E
=
=
=
=
0
0
0
0
#Check if $Roles contains Mailbox
if ($Roles -contains "Mailbox")
{
$DataDriveWarning = $DataDriveWarning_M
$DataDriveError
= $DataDriveError_M
}
else # Not Mailbox Server
{
$DataDriveWarning = $DataDriveWarning_NM
$DataDriveError
= $DataDriveError_NM
}
foreach ($Drive in $DiskTable)
{
#Looping through each drive
$DriveName
= $Drive.Name
[int]$DriveFreeSpace = $Drive.freespace
if ( $DriveName
-like "C:"
) #System Drive
{
if ( $DriveFreeSpace -ge $SystemDriveWarning)
{$SystemDriveHealth = "Good"}
elseif ( $DriveFreeSpace -ge
$SystemDriveError) {$SystemDriveHealth = "Warning"}
else {$SystemDriveHealth =
"Error"}
}
else
{
$C_DataDrive++
if ( $DriveFreeSpace -ge $DataDriveWarning)
{$C_DataDrive_G++}
elseif ( $DriveFreeSpace -ge
$DataDriveError) {$C_DataDrive_W++}
else {$C_DataDrive_E++}
} }
if ( $C_DataDrive -eq 0) # if the server only has C drive
{$DataDriveHealth = "No"}
elseif ($C_DataDrive -eq $C_DataDrive_G )
#if there is data drives also
{ $DataDriveHealth = "Good"}
elseif ($C_DataDrive_E -gt 0)
{$DataDriveHealth =
"Error"}
else {$DataDriveHealth
= "Warning" }
@{ SystemDriveHealth
DataDriveHealth
C_DataDrive_W
C_DataDrive_E
=
=
=
=
$SystemDriveHealth
$DataDriveHealth
$C_DataDrive_W
$C_DataDrive_E}
}
# <<<<< Function: Test Server Connectivity >>>>>>
function _TestConnection
{
param ($server)
if (test-Connection -ComputerName $Server -Count 2 -Quiet ) {
return $true
} else
{ return $false
}
}
# <<<<< Function: Server Up Time >>>>>>
function _UpTime
{
param($server)
$TimeNow = [DateTime]::Now
$laststart =
[System.Management.ManagementDateTimeconverter]::ToDateTime((Get-WmiObject Class Win32_OperatingSystem -computername $Server).LastBootUpTime)
if ($laststart)
{
[int]$uptimeHours = (New-TimeSpan $laststart $TimeNow).TotalHours
[int]$uptimeDays = $uptimeHours /24
[int]$MyUptime = "{0:N2}" -f $uptimeDays
}
else {$MyUptime = "N/A"}
$MyUptime
}
# <<<<< Function: Mailbox Count >>>>>>
function _GetExSvrMailboxCount
{
param($Mailboxes,$ExchangeServer,$Databases)
# The following *should* work, but it doesn't. Apparently, ServerName is
not always returned correctly which may be the cause of
# reports of counts being incorrect
#([array]($Mailboxes | Where {$_.ServerName -eq
$ExchangeServer.Name})).Count
# ..So as a workaround, I'm going to check what databases are assigned to
each server and then get the mailbox counts on a per# database basis and return the resulting total. As we already have this
information resident in memory it should be cheap, just
# not as quick.
$MailboxCount = 0
foreach ($Database in [array]($Databases | Where {$_.Server -eq
$ExchangeServer.Name}))
{
$MailboxCount+=([array]($Mailboxes | Where {$_.Database -eq
$Database.Identity})).Count
}
$MailboxCount
}
# <<<<< Function: Exchange Replication Health >>>>>>
function _GetExchReplHealth
{
param($Server)
[int]$Replication_F
$ReplicationHealth
= 0
= "N/A"
if ($Roles -contains "Mailbox")
{
[array]$Test_Replication =Test-ReplicationHealth Identity $Server
if ($Test_Replication)
{
foreach ($Test in $Test_Replication)
{
if ( $Test.Result -notlike
"Passed")
{
$ReplicationHealth = "Fail"
$Replication_F++
}
}
if ($ReplicationHealth -notlike "Fail")
{ $ReplicationHealth = "Pass"}
}
}
@{ReplicationHealth = $ReplicationHealth
Replication_F
= $Replication_F}
}
# <<<<< Function: Mailbox Server Mail Flow Test>>>>>>
function _MailboxServerTestMailFlow
{
param($Server)
$MailFlow_H
= "N/A"
if ($Roles -contains "Mailbox")
{
[array]$DBCopies = Get-MailboxServer $Server ErrorAction SilentlyContinue |Get-MailboxDatabaseCopyStatus -ErrorAction
SilentlyContinue
if ($DBCopies)
{
$MailFlow
-ErrorAction SilentlyContinue
$MailFlowResult
$MailFlow.TestMailflowResult
= Test-Mailflow $Server
=
if(! $MailFlow)
{ $MailFlow_H
= "?"}
elseif ( $MailFlowResult -like "Success")
{ $MailFlow_H
= "Pass"}
else { $MailFlow_H
= "Fail"}
}
}
$MailFlow_H
}
# <<<<< Function: Exchange Server Service Health >>>>>>
# Check to see if any Exchange Service is stopped or not
function _GetExchServiceHealth
{ param ($Server)
$ServiceDownCount = 0
$ServicesHealth
= "Fail"
#Check connectivity
if (! (get-WmiObject win32_service -ComputerName $Server))
{ $ServicesHealth = "Fail"
$ServiceDownCount = "N/A"
} # we cannot connect to the server
else # we can connect to the server and retrieve services
{
#Get Exchange services that are automatic and
stopped
$ServiceStatus = get-WmiObject win32_service ComputerName $Server |
where {($_.displayName -match "exch*") -and
($_.StartMode -match "Auto") -and($_.state -match "Stopped")}
# If any stopped services
if ($serviceStatus -ne $null)
{
foreach ($service in $serviceStatus)
{
$SvcName = $service.name
$SvcState = $service.state
$ServiceDownCount += 1
$ServicesHealth = "Fail"
}
}
else # If all services are started
{
$SvcName = "N/A"
$SvcState = "N/A"
$ServicesHealth = "Pass"
}
}
@{ServicesHealth = $ServicesHealth
ServiceDownCount = $ServiceDownCount
}
} #Function Ends
# <<<<< Function: Mailbox Server Database Copy Health >>>>>>
function _GetMailboxServerCopyStatus
{ param($Server, $Roles ,$databases)
[int]$DBCopyCount
= 1000
[int]$DBCopyCount_Mounted
= 1000
[int]$DBCopyCount_Assigned = 0
[int]$DBCopyCount_NotGood
= 1000
$dbcopy_status_H
$dbcopy_CopyQueueLength_H
= "N/A"
= "N/A"
$dbcopy_ReplayQueueLength_H = "N/A"
$dbcopy_ContentIndexState_H = "N/A"
# Check Copies Assigned to the server
$DBs =
$databases |
?
{$_.Recovery -eq $false}
$Activedbs =
@($DBs | Where {$_.Server -ieq $Server})
$DBCopyCount_Assigned = $activedbs.Count
if ($Roles -contains "Mailbox")
{
#Get other tests
$MailboxServer
= Get-MailboxServer $Server
Try
{[array]$MailboxServer_DB_copies
= $MailboxServer |
Get-MailboxDatabaseCopyStatus -ErrorAction
SilentlyContinue
if
($MailboxServer_DB_copies) #if the server has copies
{
$DBCopyCount
= $MailboxServer_DB_copies.Count
$DBCopyCount_Mounted
= 0
$DBCopyCount_NotGood
= 0
foreach ($dbcopy in $MailboxServer_DB_copies)
{
$dbcopy_status
= $dbcopy.status
$dbcopy_CopyQueueLength
= $dbcopy.CopyQueueLength
$dbcopy_ReplayQueueLength
= $dbcopy.ReplayQueueLength
$dbcopy_ContentIndexState
= $dbcopy.ContentIndexState
if (
($dbcopy_status -notlike "Mounted") -and
"Healthy")
)
($dbcopy_status -notlike
{$dbcopy_status_H = "Fail"
$DBCopyCount_NotGood++ }
if ( $dbcopy_status -like "Mounted") {$DBCopyCount_Mounted++ }
if ( $dbcopy_CopyQueueLength -gt $CopyQueueThreshold)
{$dbcopy_CopyQueueLength_H = "Fail"}
if ( $dbcopy_ReplayQueueLength -gt $ReplayQueueThreshold )
{$dbcopy_ReplayQueueLength_H = "Fail"}
if ( $dbcopy_ContentIndexState -notlike "Healthy" )
{$dbcopy_ContentIndexState_H = "Fail"}
}
if ($dbcopy_status_H
-notlike "Fail")
{ $dbcopy_status_H = "Pass" }
if ($dbcopy_CopyQueueLength_H
-notlike "Fail")
{ $dbcopy_CopyQueueLength_H = "Pass" }
if ($dbcopy_ReplayQueueLength_H
-notlike "Fail")
{ $dbcopy_ReplayQueueLength_H = "Pass" }
if ($dbcopy_ContentIndexState_H
-notlike "Fail")
{ $dbcopy_ContentIndexState_H = "Pass" }
}
}catch{}
}
#Retun hash table
@{DBCopyCount
dbcopy_status_H
DBCopyCount_Mounted
DBCopyCount_NotGood
DBCopyCount_Assigned
dbcopy_CopyQueueLength_H
dbcopy_ReplayQueueLength_H
dbcopy_ContentIndexState_H
}
=
=
=
=
=
=
=
=
$DBCopyCount
$dbcopy_status_H
$DBCopyCount_Mounted
$DBCopyCount_NotGood
$DBCopyCount_Assigned
$dbcopy_CopyQueueLength_H
$dbcopy_ReplayQueueLength_H
$dbcopy_ContentIndexState_H
}
# <<<<< Function: CAS Server MRS Test >>>>>>
function _TestCAS_MRS
{
param($Server,$Roles)
$MRS_Health
= "N/A"
if ($Roles -contains "ClientAccess")
{
[array]$MRS
ErrorAction SilentlyContinue
= Test-MRSHealth -Identity $Server -
if ($MRS)
{
foreach ($i in $MRS)
{
$i_Result = $i.passed
if ( $i_Result -ne $True )
{ $MRS_Health = "Fail"
}
}
if ($MRS_Health -notlike "Fail")
{ $MRS_Health = "Pass"}
}
}
$MRS_Health
}
# <<<<< Function: Exchange Server information >>>>>>
function _GetExSvr
{
param($ExchangeServer,$Mailboxes,$Databases)
[array]$Roles = $ExchangeServer.ServerRole.ToString().Replace("
","").Split(",");
# Set Basic Variables
$MailboxCount
= 0
$MailboxStatistics
= $null
$CopyStatus
= _GetMailboxServerCopyStatus $ExchangeServer.name
$Databases
$SvrConnection = _TestConnection $ExchangeServer.name
$Roles
If ($SvrConnection -eq $True -and $Roles -notcontains "Edge" )
{
$DiskInfoTable =
$SvrDiskHealth =
$ExchangeServer.name
$UpTime
=
$ReplHealth
=
$MailFlow
=
$ServiceHealth =
$MRS_Health
=
_GetDiskInfo $ExchangeServer.name
_GetExchDiskHealth $DiskInfoTable $Roles
_UpTime $ExchangeServer.name
_GetExchReplHealth $ExchangeServer.name $Roles
_MailboxServerTestMailFlow $ExchangeServer.name $Roles
_GetExchServiceHealth $ExchangeServer.name
_TestCAS_MRS $ExchangeServer.name $Roles
$SystemDriveHealth_Check
$SvrDiskHealth.SystemDriveHealth
$DataDriveHealth_Check
$SvrDiskHealth.DataDriveHealth
$C_DataDrive_W_Check
$C_DataDrive_E_Check
$UpTime_Check
$ReplHealth_Check
$ReplHealth.ReplicationHealth
$Replication_F_Check
$MailboxServerTestMailFlow_Check
$ServiceHealth_Check
$ServiceHealth.ServicesHealth
=
=
= $SvrDiskHealth.C_DataDrive_W
= $SvrDiskHealth.C_DataDrive_E
= $UpTime
=
= $ReplHealth.Replication_F
= $MailFlow
=
$ServiceHealthDownCount_Check
$ServiceHealth.ServiceDownCount
$MRS_Health_Check
}
else
{
$SystemDriveHealth_Check
$DataDriveHealth_Check
$C_DataDrive_W_Check
$C_DataDrive_E_Check
$UpTime_Check
$ReplHealth_Check
$Replication_F_Check
$MailboxServerTestMailFlow_Check
$ServiceHealth_Check
$ServiceHealthDownCount_Check
$MRS_Health_Check
}
=
= $MRS_Health
=
=
=
=
=
=
=
=
=
=
=
"Server
"Server
"Server
"Server
"Server
"Server
"Server
"Server
"Server
"Server
"Server
Down"
Down"
Down"
Down"
Down"
Down"
Down"
Down"
Down"
Down"
Down"
# Get O.S Information
try
{$tWMI = Get-WmiObject Win32_OperatingSystem -ComputerName
$ExchangeServer.Name -ErrorAction SilentlyContinue
$OSVersion = $tWMI.Caption.Replace("(R)","").Replace("Microsoft
","").Replace("Enterprise","En").Replace("Standard","St").Replace("
Edition","").Replace("Windows Server","Srv")
$OSServicePack = $tWMI.CSDVersion.Replace("Service Pack ","SP")}
catch {
$OSVersion = "N/A"
$OSServicePack = "N/A"}
# Get Exchange Version
$ExchangeMajorVersion = $ExchangeServer.AdminDisplayVersion.Major
$ExchangeSPLevel
= $ExchangeServer.AdminDisplayVersion.Minor
# Get Roles
if ($Roles -contains "Mailbox")
{
$MailboxCount = _GetExSvrMailboxCount -Mailboxes
$Mailboxes -ExchangeServer $ExchangeServer -Databases $Databases
# Get Mailbox Statistics the normal way, return in
a consitent format
$MailboxStatistics = Get-MailboxStatistics -Server
$ExchangeServer |
Select
DisplayName,@{Name="TotalItemSizeB";Expression={$_.TotalItemSize.Value.ToBytes(
)}},@{Name="TotalDeletedItemSizeB";Expression={$_.TotalDeletedItemSize.Value.To
Bytes()}},Database
}
# Disk Info
try{$tWMI=Get-WmiObject -query "Select * from Win32_Volume" ComputerName $ExchangeServer.Name -ErrorAction SilentlyContinue}
catch{$Disks=$null}
if ($tWMI)
{
$Disks=$tWMI | Select Name,Capacity,FreeSpace | Sort-Object Property Name
}
# Return Hashtable
@{Name
$ExchangeServer.Name.ToUpper()
ExchangeMajorVersion
ExchangeSPLevel
Edition
MailboxesCount
OSVersion
OSServicePack
Roles
Site
$ExchangeServer.Site.Name
MailboxStatistics
Disks
DBCopyCount
dbcopy_status_H
DBCopyCount_Mounted
DBCopyCount_NotGood
DBCopyCount_Assigned
dbcopy_CopyQueueLength_H
$CopyStatus.dbcopy_CopyQueueLength_H
dbcopy_ReplayQueueLength_H
$CopyStatus.dbcopy_ReplayQueueLength_H
dbcopy_ContentIndexState_H
$CopyStatus.dbcopy_ContentIndexState_H
SystemDriveHealth
DataDriveHealth
C_DataDrive_W
C_DataDrive_E
SvrConnection
UpTime
ReplHealth
Replication_F
MailboxServerTestMailFlow
ServiceHealth
ServiceHealthDownCount
MRS_Health
}
} #End Function
=
= $ExchangeMajorVersion
= $ExchangeSPLevel
= $ExchangeServer.Edition
= $MailboxCount
= $OSVersion;
= $OSServicePack
= $Roles
=
=
=
=
=
=
=
= $MailboxStatistics
= $Disks
$CopyStatus.DBCopyCount
$CopyStatus.dbcopy_status_H
$CopyStatus.DBCopyCount_Mounted
$CopyStatus.DBCopyCount_NotGood
$CopyStatus.DBCopyCount_Assigned
=
=
=
=
=
=
=
=
=
=
=
=
=
=
$SystemDriveHealth_Check
$DataDriveHealth_Check
$C_DataDrive_W_Check
$C_DataDrive_E_Check
$SvrConnection
$UpTime_Check
$ReplHealth_Check
$Replication_F_Check
$MailboxServerTestMailFlow_Check
$ServiceHealth_Check
$ServiceHealthDownCount_Check
$MRS_Health_Check
# <<<<< Function: DAG Info >>>>>>
function _GetDAG
{
param($DAG)
@{Name
= $DAG.Name.ToUpper()
MemberCount = $DAG.Servers.Count
Members
= [array]($DAG.Servers | % { $_.Name })
Databases
= @()
}
}
# Sub Function to Get Totals by Role
function _TotalsByRole
{
param($ExchangeEnvironment)
# Add Roles We Always Show
$TotalServersByRole=@{"ClientAccess"
= 0
"HubTransport"
= 0
"UnifiedMessaging" = 0
"Mailbox"
#"Edge"
}
= 0
= 0
foreach ($Site in $ExchangeEnvironment.Sites.GetEnumerator())
{
foreach ($Server in $Site.Value)
{
foreach ($Role in $Server.Roles)
{
if ($TotalServersByRole[$Role] -eq $null)
{
$TotalServersByRole.Add($Role,1)
} else {
$TotalServersByRole[$Role]++
}
}
}
}
$TotalServersByRole
}
# Sub Function to Get Totals by Version
function _TotalsByVersion
{
param($ExchangeEnvironment)
$TotalMailboxesByVersion=@{}
if ($ExchangeEnvironment.Sites)
{
foreach ($Site in $ExchangeEnvironment.Sites.GetEnumerator())
{
foreach ($Server in $Site.Value)
{
if
(!$TotalMailboxesByVersion["$($Server.ExchangeMajorVersion).$($Server.ExchangeS
PLevel)"])
{
$TotalMailboxesByVersion.Add("$($Server.ExchangeMajorVersion).$($Server.E
xchangeSPLevel)",@{ServerCount=1;MailboxCount=$Server.Mailboxes})
} else {
$TotalMailboxesByVersion["$($Server.ExchangeMajorVersion).$($Server.Excha
ngeSPLevel)"].ServerCount++
$TotalMailboxesByVersion["$($Server.ExchangeMajorVersion).$($Server.Excha
ngeSPLevel)"].MailboxCount+=$Server.Mailboxes
}
}
}
}
$TotalMailboxesByVersion
}
#----------------------------------# Section 3 - Code
#-----------------------------------
$ExchangeEnvironment = @{Sites
= @{}
Servers
DAGs
NonDAGDatabases
RecoveryDatabases
}
# Exchange Major Version String Mapping
$ExMajorVersionStrings = @{"6.0" = @{Long="E2000";Short="E2000"}
= @{}
= @()
= @()
= @()
"6.5" =
@{Long="E2003";Short="E2003"}
"8"
=
"14"
=
@{Long="E2007";Short="E2007"}
@{Long="E2010";Short="E2010"}}
# Exchange Service Pack String Mapping
$ExSPLevelStrings = @{"0" = "RTM"
"1" = "SP1"
"2" = "SP2"
"3" = "SP3"
"4" = "SP4"}
# Populate Full Mapping using above info
$ExVersionStrings = @{}
foreach ($Major in $ExMajorVersionStrings.GetEnumerator())
{
foreach ($Minor in $ExSPLevelStrings.GetEnumerator())
{
$ExVersionStrings.Add("$($Major.Key).$($Minor.Key)",@{Long="$($Major.Valu
e.Long) $($Minor.Value)";Short="$($Major.Value.Short)$($Minor.Value)"})
}
}
# 1.5.10 Exchange Role String Mapping
$ExRoleStrings = @{"Mailbox"
= @{Short="MBX";Long="Mailbox"}
"ClientAccess"
= @{Short="CAS";Long="Client
Access"}
"HubTransport"
= @{Short="HUB";Long="Hub
Transport"}
"UnifiedMessaging" = @{Short="UM";Long="Unified
Messaging"}
"Edge"
=
@{Short="EDGE";Long="Edge Transport"}
"Unknown"
= @{Short="Unknown";Long="Unknown"}}
# Get Relevant Exchange Information Up-Front
# Get Server, Exchange and Mailbox Information
write-host
write-host
write-host "2. Getting Exchange Server Objects ..." -foreground "magenta"
$ExchangeServers = [array](Get-ExchangeServer)
write-host
write-host "3. Getting Mailbox Info ... Pls wait, this may take some time" foreground "magenta"
$Mailboxes = [array](Get-Mailbox -ResultSize Unlimited -ErrorAction
SilentlyContinue -warningAction SilentlyContinue )
write-host
write-host "4. Getting Archive Mailbox Info" -foreground "magenta"
$ArchiveMailboxes = [array](Get-Mailbox -Archive -ResultSize Unlimited ErrorAction SilentlyContinue -warningAction SilentlyContinue)
write-host
write-host "5. Getting Database Info ..."
-foreground "magenta"
$Databases = [array](Get-MailboxDatabase -Status)
write-host
write-host "6. Getting DAG Info ..." -foreground "magenta"
$DAGs = [array](Get-DatabaseAvailabilityGroup)
# Populate Information we know
$ExchangeEnvironment.Add("TotalMailboxes",$Mailboxes.Count);
write-host
write-host "7. Getting Exchange Servers Health ... Pls hold, this may take
long time " -foreground "magenta"
for ($i=0; $i -lt $ExchangeServers.Count; $i++)
{
$ExSvr = _GetExSvr -ExchangeServer $ExchangeServers[$i] -Mailboxes
$Mailboxes -Databases $Databases
if (!$ExchangeEnvironment.Sites[$ExSvr.Site])
{
$ExchangeEnvironment.Sites.Add($ExSvr.Site,@($ExSvr))
} else {
$ExchangeEnvironment.Sites[$ExSvr.Site]+=$ExSvr
}
# Add to Servers List
write-host "
... Done collecting info from $($ExSvr.Name)
$ExchangeEnvironment.Servers.Add($ExSvr.Name,$ExSvr)
"
}
# Calculate Environment Totals for Role using collected data
$ExchangeEnvironment.Add("TotalServersByRole",(_TotalsByRole ExchangeEnvironment $ExchangeEnvironment))
$ExchangeEnvironment.Add("TotalMailboxesByVersion",(_TotalsByVersion ExchangeEnvironment $ExchangeEnvironment))
# Populate Environment DAGs
if ($DAGs)
{
foreach($DAG in $DAGs)
{
$ExchangeEnvironment.DAGs+=(_GetDAG -DAG $DAG)
}
}
#Databases
[decimal]$total_Archive_size
[int]$total_Archive_Count
[decimal]$total_mailboxes_size
[decimal]$Average_Archive_size
[decimal]$AverageMailboxSize
[int]$TrackAverageSize
=
=
=
=
=
=
0
0
0
0
0
0
Write-host
write-host "8. Getting Exchange Databases Health" -foreground "magenta"
for ($i=0; $i -lt $Databases.Count; $i++)
{
$Database = _GetDB -Database $Databases[$i] -ExchangeEnvironment
$ExchangeEnvironment -Mailboxes $Mailboxes -ArchiveMailboxes $ArchiveMailboxes
$DAGDB = $false
$DB_i = $Databases[$i]
write-host "
... Done collecting info from $($database.Name)"
if($DB_i.Recovery -eq $false)
{
$total_Archive_size += $database.ArchiveTotalSize
$total_Archive_Count += $Database.ArchiveMailboxCount
$total_mailboxes_size += $database.Size
$TrackAverageSize +=1
$AverageMailboxSize += $Database.MailboxAverageSize
for ($j=0; $j -lt
$ExchangeEnvironment.DAGs.Count; $j++)
{
if
($ExchangeEnvironment.DAGs[$j].Members -contains $Database.ActiveOwner)
{
$DAGDB=$true
$ExchangeEnvironment.DAGs[$j].Databases += $Database
}
}
if (!$DAGDB)
{
$ExchangeEnvironment.NonDAGDatabases += $Database
}
}
else {$ExchangeEnvironment.RecoveryDatabases += $Database }
}
$AverageMailboxSize2 = "{0:N2}" -f (($AverageMailboxSize/$TrackAverageSize)
/1073741824)
$total_Archive_size2= "{0:N2}" -f ($total_Archive_size/1073741824)
$total_mailboxes_size2 = "{0:N2}" -f ($total_mailboxes_size/1099511627776)
$Average_Archive_size2 = "{0:N2}" -f (($total_Archive_size
/$total_Archive_Count) /1073741824)
$ExchangeEnvironment.Add("TotalArchivesCount",$total_Archive_Count)
$ExchangeEnvironment.Add("TotalArchivesSize",$total_Archive_size2)
$ExchangeEnvironment.Add("TotalMailboxSize",$total_mailboxes_size2)
$ExchangeEnvironment.Add("Average_Archive_size",$Average_Archive_size2)
$ExchangeEnvironment.Add("AverageMailboxSize",$AverageMailboxSize2)
#----------------------------------# Section 4 - Create HTML
#----------------------------------# Writing html file
......................................................................
$Output="<html>
<body>
<font size=""1"" face=""Arial,sans-serif"">
<h3 align=""center"">Exchange Organization Report</h3>
<h5 align=""center"">Generated $((Get-Date).ToString())</h5>
</font>
<table border=""0"" cellpadding=""3"" style=""font-size:8pt;fontfamily:Arial,sans-serif"">
<tr bgcolor=""#009900"">
<th colspan=""$($ExchangeEnvironment.TotalMailboxesByVersion.Count)""><font
color=""#ffffff"">Total Servers:</font></th>
<th colspan=""$($ExchangeEnvironment.TotalServersByRole.Count)""><font
color=""#ffffff"">Total Roles:</font></th></tr>
<tr bgcolor=""#00CC00"">"
# Show Column Headings based on the Exchange versions we have
$ExchangeEnvironment.TotalMailboxesByVersion.GetEnumerator()|Sort Name|
%{$Output+="<th>$($ExVersionStrings[$_.Key].Short)</th>"}
$ExchangeEnvironment.TotalServersByRole.GetEnumerator()|Sort Name|
%{$Output+="<th>$($ExRoleStrings[$_.Key].Short)</th>"}
$Output+="<tr>"
$Output+="<tr align=""center"" bgcolor=""#dddddd"">"
$ExchangeEnvironment.TotalMailboxesByVersion.GetEnumerator()|Sort Name|
%{$Output+="<td>$($_.Value.ServerCount)</td>" }
$ExchangeEnvironment.TotalServersByRole.GetEnumerator()|Sort Name|
%{$Output+="<td>$($_.Value)</td>"}
$Output+="</tr><tr><tr></table><br>"
# Write Mailbox Types Table
$MailboxesTypes=$Mailboxes |Group-Object -Property Recipienttypedetails
$Output+="<font size=""1"" face=""Arial,sans-serif""></font>
<table border=""0"" cellpadding=""3"" style=""font-size:8pt;fontfamily:Arial,sans-serif"">
<tr bgcolor=""#8E1275"">"
$Output+= "<th colspan=""$($MailboxesTypes.Count)""><font
color=""#ffffff"">Mailbox Types</font></th>"
$Output+="<tr bgcolor=""#E46ACB"">"
# Show Column Headings based on the Exchange versions we have
$MailboxesTypes |Sort -Descending Count| %{$Output+="<th><font
color=""#ffffff"">$($_.Name)</font></th>"}
$Output+="<tr>"
$Output+="<tr align=""center"" bgcolor=""#dddddd"">"
$MailboxesTypes |Sort -Descending Count| %{$Output+="<td>$($_.count)</td>" }
$Output+="</tr><tr><tr></table><br />"
# Archive Mailboxes
$Output+="<font size=""1"" face=""Arial,sans-serif""></font>
<table border=""0"" cellpadding=""4"" style=""font-size:8pt;fontfamily:Arial,sans-serif"">
<tr bgcolor=""#9D9D00"">"
$Output+= "<th colspan= ""6"" ><font color=""#ffffff"">General
Statistics</font></th>"
$Output+="<tr bgcolor=""#DFE32D"">"
$Output+="<th><font color=""#000000"">Total Mailbox Count</font></th>"
$Output+="<th><font color=""#000000"">Total Mailbox Sizes (TB)</font></th>"
$Output+="<th><font color=""#000000"">Average Mailbox Size (GB)</font></th>"
$Output+="<th bgcolor=""#FFA500""><font color=""#000000"">Total Archive
Count</font></th>"
$Output+="<th bgcolor=""#FFA500""><font color=""#000000"">Total Archive Sizes
(GB)</font></th>"
$Output+="<th bgcolor=""#FFA500""><font color=""#000000"">Average Archive Size
(GB)</font></th>"
$Output+="<tr>"
$Output+="<tr align=""center"" bgcolor=""#dddddd"">"
$Output+="<td><font color=""#000000"">$($ExchangeEnvironment.TotalMailboxes)
Mailbox</font></td>"
$Output+="<td><font color=""#000000"">$($ExchangeEnvironment.TotalMailboxSize)
TB</font></td>"
$Output+="<td><font
color=""#000000"">$($ExchangeEnvironment.AverageMailboxSize) GB</font></td>"
$Output+="<td ><font
color=""#000000"">$($ExchangeEnvironment.TotalArchivesCount)
Archives</font></td>"
$Output+="<td ><font
color=""#000000"">$($ExchangeEnvironment.TotalArchivesSize) GB</font></td>"
$Output+="<td ><font
color=""#000000"">$($ExchangeEnvironment.Average_Archive_size) GB</font></td>"
$Output+="</tr><tr><tr></table><br />"
foreach ($Site in $ExchangeEnvironment.Sites.GetEnumerator())
{
$Output+=_GetOverview -Servers $Site -ExchangeEnvironment
$ExchangeEnvironment -ExRoleStrings $ExRoleStrings
}
foreach ($DAG in $ExchangeEnvironment.DAGs)
{
if ($DAG.MemberCount -gt 0)
{
# Database Availability Group Header
$Output+="<table border=""0"" cellpadding=""3"" width=""100%""
style=""font-size:8pt;font-family:Arial,sans-serif"">
<col width=""20%""><col width=""10%""><col width=""70%"">
<tr align=""center"" bgcolor=""#FF8000 "" ><th><font
color=""#ffffff"">Database Availability Group Name</font></th><th><font
color=""#ffffff"">Member Count</font></th>
<th><font color=""#ffffff"">Database Availability Group
Members<font></th></tr>
<tr><td align=""center"">$($DAG.Name)</td><td align=""center"">
$($DAG.MemberCount)</td><td align=""center"">"
$DAG.Members | % { $Output+="$($_) " }
$Output+="</td></tr></table>"
# Get Table HTML
$Output+=_GetDBTable -Databases $DAG.Databases
}
}
if ($ExchangeEnvironment.NonDAGDatabases.Count)
{
$Output+="<table border=""0"" cellpadding=""3"" width=""100%""
style=""font-size:8pt;font-family:Arial,sans-serif"">
<tr bgcolor=""#FF8000""><th><font color=""#ffffff"">Mailbox Databases
(Non-DAG)</font></th></table>"
$Output+=_GetDBTable -Databases $ExchangeEnvironment.NonDAGDatabases
}
if ($ExchangeEnvironment.RecoveryDatabases.Count)
{
Write-Host
write-host "9. Getting Recovery Databases" -foreground "magenta"
$Output+="<table border=""0"" cellpadding=""3"" width=""100%""
style=""font-size:8pt;font-family:Arial,sans-serif"">
<tr bgcolor=""#000000""><th><font color=""#ffffff""><Strong>Recovery
Databases </font></strong></th></table>"
$Output+=_GetRecoveryDBTable -Databases
$ExchangeEnvironment.RecoveryDatabases
}
$Output+="</body></html>";
Add-Content $filename1 $Output
#----------------------------------# Section 5 - Drawing Part
#----------------------------------write-host
write-host "10. Generating Drawings" -foreground "magenta"
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#<<<<<<<<Draw DBs per Server Per DAG>>>>>>>>
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$Tem1 =$null
$Tem1 =$null
$Tem2 = @{}
foreach ($DAG in $ExchangeEnvironment.DAGS)
{
$DAGNAME = $DAG.NAME
$Tem1 =$null
$Tem1 =$null
$Tem2 = @{}
Foreach ($member in $DAG.members)
{
$Tem1 = $ExchangeEnvironment.servers["$member"]
$Tem2.Add($Tem1.name ,$Tem1.DBCopyCount_Assigned)
}
# load the appropriate assemblies
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisu
alization")
# create chart object
$Chart = New-object
System.Windows.Forms.DataVisualization.Charting.Chart
$Chart.Width = 700
$Chart.Height = 700
$Chart.Left = 70
$Chart.Top = 70
# create a chartarea to draw on and add to chart
$ChartArea = New-Object
System.Windows.Forms.DataVisualization.Charting.ChartArea
$Chart.ChartAreas.Add($ChartArea)
$titlefont=new-object
system.drawing.font("ARIAL",12,[system.drawing.fontstyle]::bold)
$title =New-Object
System.Windows.Forms.DataVisualization.Charting.title
$chart.titles.add($title)
$chart.titles[0].text = "# Database mounted per server $DAGNAME "
$chart.titles[0].font = $titlefont
$chart.titles[0].forecolor = "Red"
[void]$Chart.Series.Add("Data")
$Chart.Series["Data"].Points.DataBindXY($Tem2.keys,
$tem2.values)
$Chart.Series["Data"].IsvalueShownAsLabel=$true
$legend1 = new-object
System.Windows.Forms.DataVisualization.Charting.Legend
$legend1.BorderColor = "Black"
$legend1.Docking = "Top"
$legend1.Alignment = "Center"
$legend1.LegendStyle = "Row"
$legend1.BackColor = [System.Drawing.Color]::Transparent
$chart.Legends.Add($legend1)
# set chart type
$Chart.Series["Data"].ChartType =
[System.Windows.Forms.DataVisualization.Charting.SeriesChartType]::Doughnut
# set chart options
$Chart.Series["Data"]["PieLabelStyle"] = "Outside"
$Chart.Series["Data"]["PieLineColor"] = "Black"
$Chart.Series["Data"]["PieDrawingStyle"] = "Concave"
($Chart.Series["Data"].Points.FindMaxByValue())["Exploded"] =
$true
$Chart.Series["Data"]["PieLabelStyle"] = "Outside";
$chart.Series["Data"]["PieDrawingStyle"] = "SoftEdge"
$chart.Series["Data"]["DoughnutRadius"] = "60"
# save chart to file
$Chart.SaveImage("F:\ScheduledScripts\Pilot\$DAGname - DBs Per
server.jpeg", "jpeg")
}
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#<<<<<<<<Draw DB Sizes>>>>>>>>
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisu
alization")
# create chart object
$Chart = New-object
System.Windows.Forms.DataVisualization.Charting.Chart
$Chart.Width
= 800
$Chart.Height
= 400
$Chart.Left
= 900
$Chart.Top
= 80
$CHART.BackColor = "red"
# create a chartarea to draw on and add to chart
$ChartArea = New-Object
System.Windows.Forms.DataVisualization.Charting.ChartArea
$Chart.ChartAreas.Add($ChartArea)
$chartarea.backcolor = "White"
$titlefont=new-object
system.drawing.font("ARIAL",12,[system.drawing.fontstyle]::bold)
$title =New-Object
System.Windows.Forms.DataVisualization.Charting.title
$chart.titles.add($title)
$chart.titles[0].text = "Database Sizes "
$chart.titles[0].font = $titlefont
$chart.titles[0].forecolor = "Red"
#add data to chart
[array]$Chart_Databases = $databases | where { $_.recovery -eq
$false }| Sort-Object -Property Databasesize | Select-Object Name,DATABASESIZE
$Chart_Databases_Names = @(foreach($Chart_DB in
$Chart_Databases){$Chart_DB.Name})
$Chart_Databases_Sizes = @(foreach($Chart_DB in
$Chart_Databases){($Chart_DB.Databasesize.togb())})
[void]$Chart.Series.Add("Data")
$Chart.Series["Data"].Points.DataBindXY($Chart_Databases_Names,
$Chart_Databases_Sizes)
$Chart.Series["Data"].IsvalueShownAsLabel=$true
# add title and axes labels
$ChartArea.AxisX.Title = " "
$chartArea.AxisY.Title = "Size in GB"
$ChartArea.AxisX.Interval=1
# Find point with max/min values and change their colour
$maxValuePoint = $Chart.Series["Data"].Points.FindMaxByValue()
$maxValuePoint.Color = [System.Drawing.Color]::Red
$minValuePoint = $Chart.Series["Data"].Points.FindMinByValue()
$minValuePoint.Color = [System.Drawing.Color]::Green
# change chart area colour
$Chart.BackColor = "WHITE"
$chart.Series["Data"]["DrawingStyle"] = "Emboss"
# save chart to file
$Chart.SaveImage("F:\ScheduledScripts\Pilot\Database size.jpeg",
"JPEG")
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#<<<<<<<<Mailbox Count Per DB>>>>>>>>
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisu
alization")
# create chart object
$Chart = New-object
System.Windows.Forms.DataVisualization.Charting.Chart
$Chart.Width = 1100
$Chart.Height =500
# create a chartarea to draw on and add to chart
$ChartArea = New-Object
System.Windows.Forms.DataVisualization.Charting.ChartArea
$Chart.ChartAreas.Add($ChartArea)
$chartarea.backcolor =
"White"
$titlefont=new-object
system.drawing.font("ARIAL",12,[system.drawing.fontstyle]::bold)
$title =New-Object
System.Windows.Forms.DataVisualization.Charting.title
$chart.titles.add($title)
$chart.titles[0].text = "Mailbox Distribution"
$chart.titles[0].font = $titlefont
$chart.titles[0].forecolor = "Red"
$DB_Hash =$null
$DB_Hash = @{}
$mydbs= $null
$mydbs =@()
if ($ExchangeEnvironment.NonDAGDatabases.Count)
{
foreach( $tempobj in
$ExchangeEnvironment.NonDAGDatabases)
{
foreach ($Database in $Databases)
{
IF
($Database.name -like $tempobj.name)
{$objmailboxcount= New-Object System.Object
$objmailboxcount | Add-Member -type NoteProperty -name Name -value
$database.name
$objmailboxcount | Add-Member -type NoteProperty -name count -value
$tempobj.mailboxcount
$mydbs
+=
$objmailboxcount
}
}
}
}
foreach ($DAG in $ExchangeEnvironment.DAGs)
{
if ($DAG.MemberCount -gt 0)
{
foreach ($tempobj in $DAG.Databases)
{
foreach ($Database in $Databases)
{
IF ($Database.name -like $tempobj.name)
{
$objmailboxcount= NewObject System.Object
$objmailboxcount | Add-Member -type NoteProperty -name Name -value
$database.name
$objmailboxcount | Add-Member -type NoteProperty -name count -value
$tempobj.mailboxcount
$mydbs +=
$objmailboxcount
}
}
}
}
}
$mydbs =
$mydbs |Sort-Object -Property count
$temparray =@()
[array]$temparray2=@()
for ($i=0; $i -lt $mydbs.Count; $i++)
{
$temparray+= $mydbs["$i"].name
[string]$tempholder = $mydbs["$i"].count
$temparray2 += $tempholder
}
[void]$Chart.Series.Add("Data")
$Chart.Series["Data"].Points.DataBindXY( $temparray,$temparray2
)
$Chart.Series["Data"].IsvalueShownAsLabel=$true
# add title and axes labels
$ChartArea.AxisX.Title = " "
$chartArea.AxisY.Title = "Mailboxes"
$ChartArea.AxisX.Interval=1
#Find point with max/min values and change their colour
$maxValuePoint = $Chart.Series["Data"].Points.FindMaxByValue()
$maxValuePoint.Color = [System.Drawing.Color]::Red
$minValuePoint = $Chart.Series["Data"].Points.FindMinByValue()
$minValuePoint.Color = [System.Drawing.Color]::Green
# change chart area colour
$Chart.BackColor = "WHITE"
$Chart.Series["Data"]["DrawingStyle"] = "cylinder"
$chart.Series["Data"]["DrawingStyle"] = "Emboss"
# save chart to file
$Chart.SaveImage("F:\ScheduledScripts\Pilot\Database Vs
Mailboxes.JPEG", "JPEG")
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#<<<<<<<<Mailboxes Per Server>>>>>>>>
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisu
alization")
#Collect Data
$myservers =$null
$myservers = @()
foreach ($DAG in $ExchangeEnvironment.DAGS)
{
foreach ($Serv in $DAG.members)
{
$mymailboxcount =
$ExchangeEnvironment.servers["$serv"].mailboxescount
$objcount= New-Object
System.Object
$objcount| Add-Member -type
NoteProperty -name Name -value $serv
$objcount | Add-Member -type
NoteProperty -name count -value $mymailboxcount
$myservers +=
$objcount
}
}
# create chart object
$Chart = New-object
System.Windows.Forms.DataVisualization.Charting.Chart
$Chart.Width = 1200
$Chart.Height = 700
$Chart.Left = 70
$Chart.Top = 100
# create a chartarea to draw on and add to chart
$ChartArea = New-Object
System.Windows.Forms.DataVisualization.Charting.ChartArea
$Chart.ChartAreas.Add($ChartArea)
$temparray =@()
[array]$temparray2=@()
for ($i=0; $i -lt $myservers.Count; $i++)
{
$temparray+= $myservers["$i"].name
[string]$tempholder = $myservers["$i"].count
$temparray2 += $tempholder
}
$titlefont=new-object
system.drawing.font("ARIAL",12,[system.drawing.fontstyle]::bold)
$title =New-Object
System.Windows.Forms.DataVisualization.Charting.title
$chart.titles.add($title)
$chart.titles[0].text = "# Mailboxes vs Servers "
$chart.titles[0].font = $titlefont
$chart.titles[0].forecolor = "Red"
#add data to chart
[void]$Chart.Series.Add("Data")
$Chart.Series["Data"].Points.DataBindXY($temparray,
$temparray2)
$Chart.Series["Data"].IsvalueShownAsLabel=$true
#Find point with max/min values and change their colour
$maxValuePoint = $Chart.Series["Data"].Points.FindMaxByValue()
$maxValuePoint.Color = [System.Drawing.Color]::Red
$minValuePoint = $Chart.Series["Data"].Points.FindMinByValue()
$minValuePoint.Color = [System.Drawing.Color]::Green
# set chart type
$Chart.Series["Data"].ChartType =
[System.Windows.Forms.DataVisualization.Charting.SeriesChartType]::bar
$Chart.Series["Data"]["DrawingStyle"] = "emboss"
# save chart to file
$Chart.SaveImage("F:\ScheduledScripts\Pilot\Mailboxes Vs
Servers.jpeg","jpeg")
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#<<<<<<<<Draw DB Backup>>>>>>>>
#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisu
alization")
# create chart object
$Chart = New-object
System.Windows.Forms.DataVisualization.Charting.Chart
$Chart.Width = 1100
$Chart.Height =500
# create a chartarea to draw on and add to chart
$ChartArea = New-Object
System.Windows.Forms.DataVisualization.Charting.ChartArea
$Chart.ChartAreas.Add($ChartArea)
$chartarea.backcolor =
"White"
$titlefont=new-object
system.drawing.font("ARIAL",12,[system.drawing.fontstyle]::bold)
$title =New-Object
System.Windows.Forms.DataVisualization.Charting.title
$chart.titles.add($title)
$chart.titles[0].text = "DB Backup"
$chart.titles[0].font = $titlefont
$chart.titles[0].forecolor = "Red"
$DB_Hash_one =$null
$DB_Hash_one = @{}
$mydbs_one= $null
$mydbs_one =@()
if ($ExchangeEnvironment.NonDAGDatabases.Count)
{
foreach( $Obj_one in
$ExchangeEnvironment.NonDAGDatabases)
{
$objbackup = NewObject System.Object
$objbackup | AddMember -type NoteProperty -name Name -value $Obj_one.name
$objbackup | AddMember -type NoteProperty -name count -value $Obj_one.HowOldBackup
$mydbs_one +=
$objbackup
}
}
foreach ($DAG in $ExchangeEnvironment.DAGs)
{
if ($DAG.MemberCount -gt 0)
{
foreach ($Obj_one in
$DAG.Databases)
{
$objbackup = NewObject System.Object
$objbackup | AddMember -type NoteProperty -name Name -value $Obj_one.name
$objbackup | AddMember -type NoteProperty -name HowOldBackup -value $Obj_one.HowOldBackup
$mydbs_one +=
$objbackup
}
}
}
$mydbs_one =
$mydbs_one |Sort-Object -Property HowOldBackup
$temparray_one =@()
[array]$temparray2_one=@()
for ($i=0; $i -lt $mydbs_one.Count; $i++)
{
$temparray_one+= $mydbs_one["$i"].name
[string]$tempholder_one =
$mydbs_one["$i"].HowOldBackup
$temparray2_one += $tempholder_one
}
[void]$Chart.Series.Add("Data")
$Chart.Series["Data"].Points.DataBindXY(
$temparray_one,$temparray2_one )
$Chart.Series["Data"].IsvalueShownAsLabel=$true
# add title and axes labels
$ChartArea.AxisX.Title = " "
$chartArea.AxisY.Title = "Days since backup"
$ChartArea.AxisX.Interval=1
#Find point with max/min values and change their colour
$maxValuePoint = $Chart.Series["Data"].Points.FindMaxByValue()
$maxValuePoint.Color = [System.Drawing.Color]::Red
$minValuePoint = $Chart.Series["Data"].Points.FindMinByValue()
$minValuePoint.Color = [System.Drawing.Color]::Green
# change chart area colour
$Chart.BackColor = "WHITE"
$Chart.Series["Data"]["DrawingStyle"] = "cylinder"
$chart.Series["Data"]["DrawingStyle"] = "Emboss"
# save chart to file
$Chart.SaveImage("F:\ScheduledScripts\Pilot\Database
Backup.JPEG", "JPEG")
#----------------------------------# Section 6 - Send Email
#----------------------------------write-host
write-host "11. Sending Email" -foreground "magenta"
sendEmail $EmailSender $EmailTo "Mail Health Report _$(Get-Date -f 'yyyy-MMdd')" $EmailSMTP $fileName1
#----------------------------------#
#----------------------------------#Displaying info
Sleep 2
Write-Host
Write-Host
write-host "--------------------------"
write-host "Script Ends" -foreground Green
write-host "--------------------------"
write-host
write-host
write-host
write-host "Don't worry if you have errors..This only means that the script
couldn't reach a server or does not have permissions. Totally Normal"
write-host
write-host "Check your email for results... Remember that you need to open the
script and customize thresholds under the script customization section.Make
sure to read the script release notes"
write-host
write-host "If you didn't receive email, then this is maybe because you didn't
edit the script to enter your email settings"
write-host
write-host
write-host
write-host
#----------------------------------# Script Ends
#-----------------------------------
Download