<#-------------# 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 #-----------------------------------