Skip to content

Instantly share code, notes, and snippets.

@theagreeablecow
Last active July 4, 2018 00:18
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save theagreeablecow/5890371 to your computer and use it in GitHub Desktop.
SAMReport Module for Exchange
############################################################################################################
# Module Variables - Exchange #
#----------------------------------#
# Customise report Variables
$EmailTo = $EmailTo
$EmailSubject = $EmailSubject
$ReportTitle = $ReportTitle
$ReportSubTitle = $ReportSubTitle
# Load required plug-ins
if (!(Get-PSSnapin | where {$_.Name -eq "Microsoft.Exchange.Management.PowerShell.E2010"})){
Write-Verbose "Loading the Exchange 2010 snapin"
try{
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction STOP
}
catch{
#Snapin not loaded
Write-Warning $_.Exception.Message
EXIT
}
. $env:ExchangeInstallPath\bin\RemoteExchange.ps1
Connect-ExchangeServer -auto -AllowClobber
}
<#
FUTURE - NOT YET FUNCTIONAL
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://$Exchange_Server/PowerShell/ -Authentication Kerberos -Credential $Credentials
Import-PsSession $Session
#>
# Load server and array information
$ExchangeServers = @(Get-ExchangeServer | where {$_.ServerRole -ne "Edge"})
$TransportServers = @(Get-TransportServer | where {$_.ServerRole -ne "Edge"})
$CASServers = @(Get-ClientAccessServer)
$DAGs = @(Get-DatabaseAvailabilityGroup -Status)
<#
$OU = "OU=MyServers,DC=mydomain,DC=com,DC=au"
$Servers = Get-ADComputer -Filter {OperatingSystem -Like "Windows *Server*"} -SearchBase $OU | Select-Object –ExpandProperty Name
$Servers = @("Server1","Server2","Server3")
$Servers = Get-Content .\<path>\servers.txt
$Servers = ($env:COMPUTERNAME)
#>
#Miscellaneous
############################################################################################################
# Info #
#------------------------
$Title = "Environment Summary"
$Comment = "This module shows an overview of the Exchange environment"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
#Thresholds
[int]$UpTimeMax = 180 #Days
[int]$UpTimeWarning = 90 #Days
#Create an Array and run query
$ResultsData = @()
#Ref: http://social.technet.microsoft.com/wiki/contents/articles/240.exchange-server-and-update-rollups-build-numbers.aspx
# http://social.technet.microsoft.com/wiki/contents/articles/15776.exchange-server-2013-and-cumulative-updates-cus-build-numbers.aspx
$VersionArray = ("Exchange Server 2010 RTM","14.00.0639.021"),
("Exchange Server 2010 Update Rollup 1","14.00.0682.001"),
("Exchange Server 2010 Update Rollup 2","14.00.0689.000"),
("Exchange Server 2010 Update Rollup 3","14.00.0694.000"),
("Exchange Server 2010 Update Rollup 4","14.00.0702.001"),
("Exchange Server 2010 Update Rollup 5","14.00.0726.000"),
("Exchange Server 2010 SP1 RTM","14.01.0218.015"),
("Exchange Server 2010 SP1 Update Rollup 1","14.01.0255.002"),
("Exchange Server 2010 SP1 Update Rollup 2","14.01.0270.001"),
("Exchange Server 2010 SP1 Update Rollup 3","14.01.0289.003"),
("Exchange Server 2010 SP1 Update Rollup 3 v3","14.01.0289.007"),
("Exchange Server 2010 SP1 Update Rollup 4","14.01.0323.001"),
("Exchange Server 2010 SP1 Update Rollup 4 v2","14.01.0323.006"),
("Exchange Server 2010 SP1 Update Rollup 5","14.01.0339.001"),
("Exchange Server 2010 SP1 Update Rollup 6","14.01.0355.002"),
("Exchange Server 2010 SP1 Update Rollup 7","14.01.0421.000"),
("Exchange Server 2010 SP1 Update Rollup 7 v2","14.01.0421.002"),
("Exchange Server 2010 SP1 Update Rollup 7 v3","14.01.0421.003"),
("Exchange Server 2010 SP1 Update Rollup 8","14.01.0438.000"),
("Exchange Server 2010 SP2 RTM","14.02.0247.005"),
("Exchange Server 2010 SP2 Update Rollup 1","14.02.0283.003"),
("Exchange Server 2010 SP2 Update Rollup 2","14.02.0298.004"),
("Exchange Server 2010 SP2 Update Rollup 3","14.02.0309.002"),
("Exchange Server 2010 SP2 Update Rollup 4","14.02.0318.002"),
("Exchange Server 2010 SP2 Update Rollup 4 v2","14.02.0318.004"),
("Exchange Server 2010 SP2 Update Rollup 5","14.02.0328.005"),
("Exchange Server 2010 SP2 Update Rollup 5 v2","14.02.0328.010"),
("Exchange Server 2010 SP2 Update Rollup 6","14.02.0342.003"),
("Exchange Server 2010 SP3 RTM","14.03.0123.004"),
("Exchange Server 2010 SP3 Update Rollup 1","14.03.0146.000"),
("Exchange Server 2010 SP3 Update Rollup 2","14.03.0158.001"),
("Exchange Server 2010 SP3 Update Rollup 3","14.03.0169.001"),
("Exchange Server 2010 SP3 Update Rollup 4","14.03.0174.001"),
("Exchange Server 2013 Preview","15.00.0466.013"),
("Exchange Server 2013 RTM","15.00.0516.032"),
("Exchange Server 2013 Cumulative Update 1","15.00.0620.029"),
("Exchange Server 2013 Cumulative Update 2","15.00.0712.024"),
("Exchange Server 2013 Cumulative Update 3","15.00.0775.038")
# Add results into the array
foreach ($Server in $ExchangeServers){
# Get Exchange Version
if ($Server.AdminDisplayVersion.Major -eq 14){
$fileinfo = Get-Command "\\$Server\c$\program files\microsoft\exchange server\v14\bin\exsetup.exe" | %{$_.fileversioninfo}
}
elseif ($Server.AdminDisplayVersion.Major -eq 15){
$fileinfo = Get-Command "\\$Server\c$\program files\microsoft\exchange server\v15\bin\exsetup.exe" | %{$_.fileversioninfo}
}
$FileVersion = $fileinfo.FileVersion
for($n=0;$n -lt $versionArray.count; $n++){
if($FileVersion -eq $versionArray[$n][1]){
$ExchangeVersion = $versionArray[$n][0]
}
}
#Trim Site Names
$Site = $Server.Site -replace "/Configuration/Sites/", " - "
#Format Build Date
$Created = ($Server.WhenCreated).ToString("dd/MM/yyyy")
#DNS Test
try {
$ip = @([System.Net.Dns]::GetHostByName($server).AddressList | Select-Object IPAddressToString -first 1 -ExpandProperty IPAddressToString)
}
catch{
$IP = $NULL
}
if ($IP -eq $NULL){
$DNS = "!RED!Failed"
$AlertText += "!RED!Unable to resolve IP Address for $Server </br>"
$AlertCount += $AlertCount.count + 1
}
else{
$DNS = "!GREEN!Passed"
}
#Ping Test
$PingTest = Test-Connection $Server -count 2 -Quiet -ErrorAction Stop
if ($PingTest -eq $False){
$Ping = "!RED!Failed"
$AlertText += "!RED!Unable to ping IP Address for $Server </br>"
$AlertCount += $AlertCount.count + 1
}
else{
$Ping = "!GREEN!Passed"
}
#Uptime Test
$UpTime = $NULL
$LastBootUpTime = $NULL
$LastBootUpTime = [System.Management.ManagementDateTimeconverter]::ToDateTime((Get-WmiObject -Class Win32_OperatingSystem -computername $Server -ErrorAction Stop).LastBootUpTime)
[int]$UpTime = "{0:N0}" -f (New-TimeSpan $LastBootUpTime $Date).TotalDays
$UpTime = $UpTime + 1
if ($UpTime -ge $UpTimeMax){
$AlertText += "!RED!$Server has not been restarted for a VERY long time </br>"
$AlertCount += $AlertCount.count + 1
}
elseif ($UpTime -ge $UpTimeWarning){
$WarningText += "!ORANGE!$Server has not been restarted for a long time </br>"
$WarningCount += $WarningCount.count + 1
}
if ($UpTime -lt 1){
$WarningText += "!ORANGE!$Server has been restarted in the past 24 hours </br>"
$WarningCount += $WarningCount.count + 1
}
#OS Version
$tWMI = Get-WmiObject Win32_OperatingSystem -ComputerName $Server -ErrorAction SilentlyContinue
if ($tWMI){
$OSVersion = $tWMI.Caption.Replace("(R)","").Replace("Microsoft ","").Replace("Enterprise","Ent").Replace("Standard","Std").Replace(" Edition","")
$OSServicePack = $tWMI.CSDVersion
}
else {
$OSVersion = "N/A"
$OSServicePack = "N/A"
}
#Build Array
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -name "Name" -value $Server.Name
$obj | Add-Member -MemberType NoteProperty -name "Site" -value $Site
$obj | Add-Member -MemberType NoteProperty -name "Version" -value $ExchangeVersion
$obj | Add-Member -MemberType NoteProperty -name "Role(s)" -value $Server.ServerRole
$obj | Add-Member -MemberType NoteProperty -name "Edition" -value $Server.Edition
$obj | Add-Member -MemberType NoteProperty -name "Operating System" -value "$OSVersion $OSServicePack"
$obj | Add-Member -MemberType NoteProperty -name "Build Date" -value $Created
$obj | Add-Member -MemberType NoteProperty -name "DNS" -value $DNS
$obj | Add-Member -MemberType NoteProperty -name "Ping" -value $Ping
$obj | Add-Member -MemberType NoteProperty -name "Uptime" -value "$UpTime days"
$ResultsData += $obj
}
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Name"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "Services Check"
$Comment = "This module checks that the appropriate services are running, according to the role(s) on each server"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
#Create an Array and run query
$ResultsData = @()
$FailedServices = @()
# Add results into the array
foreach ($Server in $ExchangeServers){
$ServiceHealth = @(Test-ServiceHealth $server -ErrorAction Stop)
foreach($Service in $ServiceHealth){
$Failed = ""
$RoleName = $Service.Role
if ($Service.RequiredServicesRunning -eq $True){
$Status = "Passed"
}
elseif ($Service.RequiredServicesRunning -eq $False){
$Status = "Failed"
$FailedServices = $Service.ServicesNotRunning
ForEach ($FailedService in $FailedServices){
$Failed += $FailedService
}
$AlertText += "!RED!Required services not running on $Server for $RoleName </br>"
$AlertCount += $AlertCount.count + 1
}
#Build Array
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -name "Name" -value $Server.Name
$obj | Add-Member -MemberType NoteProperty -name "Role" -value $RoleName
$obj | Add-Member -MemberType NoteProperty -name "Service Health" -value $Status
$obj | Add-Member -MemberType NoteProperty -name "Services Not Running" -value $Failed
$ResultsData += $obj
}
}
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Name"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "Transport Queues"
$Comment = "This module checks for delayed messages in Transport Queues"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
#Thresholds
[int]$QueueMax = 100
[int]$QueueWarning = 50
#Create an Array and run query
$ResultsData = @()
$Queues = @()
# Add results into the array
foreach ($Server in $TransportServers){
$Queues = Get-Queue -Server $Server | select-object Identity,DeliveryType,Status,MessageCount,LastRetryTime,NextRetryTime,NextHopDomain
foreach ($Queue in $Queues){
#Message Count
$MessageCount = $Queue.MessageCount
if ($MessageCount -gt $QueueMax){
$AlertText += "!RED!Exesive queue count for $Server </br>"
$AlertCount += $AlertCount.count + 1
}
elseif ($MessageCount -gt $QueueWarning){
$AlertText += "!ORANGE!Long queue count for $Server </br>"
$WarningCount += $WarningCount.count + 1
}
#Build Array
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -name "Name" -value $Server.Name
$obj | Add-Member -MemberType NoteProperty -name "Identity" -value $Queue.Identity
$obj | Add-Member -MemberType NoteProperty -name "Delivery Type" -value $Queue.DeliveryType
$obj | Add-Member -MemberType NoteProperty -name "Status" -value $Queue.Status
$obj | Add-Member -MemberType NoteProperty -name "Count" -value $MessageCount
$obj | Add-Member -MemberType NoteProperty -name "Last Retry" -value $Queue.LastRetryTime
$obj | Add-Member -MemberType NoteProperty -name "Next Retry" -value $Queue.NextRetryTime
$obj | Add-Member -MemberType NoteProperty -name "Next Hop" -value $Queue.NextHopDomain
$ResultsData += $obj
}
}
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Name"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "Database Mount Status"
$Comment = "This module checks the mount status of Public folder and Mailbox databases"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
#Create an Array and run query
$ResultsData = @()
$AllDBs = @()
# Add results into the array
foreach ($Server in $ExchangeServers){
if ($Server.IsMailboxServer -eq $True){
$MailboxDBs = @(Get-MailboxDatabase -server $Server -status | Where {$_.MountedOnServer -eq ($Server.fqdn)})
$PublicFolderDBs = @(Get-PublicFolderDatabase -server $Server -status)
$AllDBs = $MailboxDBs + $PublicFolderDBs | Select-object name,server,mounted,EdbFilePath,LogFolderPath
foreach ($DB in $AllDBs){
#Unmounted DBs
if($DB.Mounted -eq $False){
$DBName = $DB.Name
$AlertText += "!RED!$DBName is not mounted on $Server </br>"
$AlertCount += $AlertCount.count + 1
}
#Build Array
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -name "Name" -value $DB.Name
$obj | Add-Member -MemberType NoteProperty -name "Mounted" -value $DB.Mounted
$obj | Add-Member -MemberType NoteProperty -name "Server" -value $DB.Server
$obj | Add-Member -MemberType NoteProperty -name "EDB File" -value $DB.EdbFilePath
$obj | Add-Member -MemberType NoteProperty -name "Log Path" -value $DB.LogFolderPath
$ResultsData += $obj
}
}
}
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Name"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "DAG Database Health Status"
$Comment = "This module checks the health status of the Databases which are part of a Database Availability Group"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
#Thresholds
[int]$CopyQueueMax = 200
[int]$CopyQueueWarning = 50
[int]$ReplayQueueMax = 200
[int]$ReplayQueueWarning = 50
#Create an Array and run query
$ResultsData = @()
# Add results into the array
foreach ($DAG in $DAGs){
#Get DAG databases and Copy Status
$DAGdb = @(Get-MailboxDatabase -Status | Where-Object {$_.MasterServerOrAvailabilityGroup -eq $DAG.Name} | Sort-Object Name)
foreach ($DB in $DAGdb) {
$DBCopyStatus = @($DB | Get-MailboxDatabaseCopyStatus)
foreach ($DBCopy in $DBCopyStatus){
#Get Database Copy Info
$DBCopyName = $DBCopy.DatabaseName
$MailboxServer = $DBCopy.MailboxServer
$DBPreference = ($DB | Select-Object -ExpandProperty ActivationPreference | Where-Object {$_.Key -eq $MailboxServer}).Value
$CopyStatus = $DBCopy.Status
[int]$CopyQueueLength = $DBCopy.CopyQueueLength
[int]$ReplayQueueLength = $DBCopy.ReplayQueueLength
$ContentIndexState = $DBCopy.ContentIndexState
#Get Replay Lagged Info
$ReplayLagCopies = @($DB | Select -ExpandProperty ReplayLagTimes | Where-Object {$_.Value -gt 0})
if ($($ReplayLagCopies.count) -gt 0){
[bool]$ReplayLag = $False
foreach ($ReplayLagCopy in $ReplayLagCopies){
if ($ReplayLagCopy.Key -eq $MailboxServer){
[bool]$ReplayLag = $true
}
}
}
else{
[bool]$ReplayLag = $false
}
#Get Truncation Lag Info
$TruncationLagCopies = @($DB | Select -ExpandProperty TruncationLagTimes | Where-Object {$_.Value -gt 0})
if ($($TruncationLagCopies.count) -gt 0){
[bool]$TruncateLag = $False
foreach ($TruncationLagCopy in $TruncationLagCopies){
if ($TruncationLagCopy.Key -eq $MailboxServer){
[bool]$TruncateLag = $True
}
}
}
else{
[bool]$TruncateLag = $False
}
#Check Database Preference
if (($DBPreference -eq 1) -AND ($CopyStatus -ne 'Mounted')){
$WarningText += "!ORANGE!$DBCopyName is not mounted on its preferred server </br>"
$WarningCount += $WarningCount.count + 1
}
#Check Copy Mount Status
if (($CopyStatus -ne "Mounted") -and ($CopyStatus -ne "Healthy")){
$AlertText += "!RED!$DBCopyName is reporting a Copy Status of $CopyStatus on $MailboxServer</br>"
$AlertCount += $AlertCount.count + 1
}
#Check Copy Queue Length
if ($CopyQueueLength -ge $CopyQueueMax){
$AlertText += "!RED!$DBCopyName has a VERY high Copy Queue Length of $CopyQueueLength on $MailboxServer</br>"
$AlertCount += $AlertCount.count + 1
}
elseif ($CopyQueueLength -ge $CopyQueueWarning){
$WarningText += "!ORANGE!$DBCopyName has a high Copy Queue Length of $CopyQueueLength on $MailboxServer</br>"
$WarningCount += $WarningCount.count + 1
}
#Check Replay Queue Length
if ($ReplayQueueLength -ge $ReplayQueueMax){
$AlertText += "!RED!$DBCopyName has a VERY high Replay Queue Length of $ReplayQueueLength on $MailboxServer</br>"
$AlertCount += $AlertCount.count + 1
}
elseif ($ReplayQueueLength -ge $ReplayQueueWarning){
$WarningText += "!ORANGE!$DBCopyName has a high Replay Queue Length of $ReplayQueueLength on $MailboxServer</br>"
$WarningCount += $WarningCount.count + 1
}
#Check Content Index State
if ($ContentIndexState -ne "Healthy"){
$AlertText += "!RED!$DBCopyName is reporting a Content Index State of $ContentIndexState on $MailboxServer</br>"
$AlertCount += $AlertCount.count + 1
}
#Build Array
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -name "Database Copy" -value $DBCopyName
$obj | Add-Member -MemberType NoteProperty -name "Preference" -value $DBPreference
$obj | Add-Member -MemberType NoteProperty -name "Server" -value $MailboxServer
$obj | Add-Member -MemberType NoteProperty -name "Status" -value $CopyStatus
$obj | Add-Member -MemberType NoteProperty -name "Copy Queue" -value $CopyQueueLength
$obj | Add-Member -MemberType NoteProperty -name "Replay Queue" -value $ReplayQueueLength
$obj | Add-Member -MemberType NoteProperty -name "Content Index" -value $ContentIndexState
$obj | Add-Member -MemberType NoteProperty -name "Replay Lagged" -value $ReplayLag
$obj | Add-Member -MemberType NoteProperty -name "Truncation Lagged" -value $TruncateLag
$ResultsData += $obj
}
}
}
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Database Copy","Preference"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "DAG Replication Health Status"
$Comment = "This module checks the health status of the Database Availability Group replication"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
#Create an Array and run query
$ResultsData = @()
# Add results into the array
foreach ($DAG in $DAGs){
$DAGMembers = @($DAG | Select-Object -ExpandProperty Servers | Sort-Object Name)
foreach ($DAGMember in $DAGMembers){
$ReplicationHealth = Test-ReplicationHealth -Server $DAGMember
foreach ($HealthCheck in $ReplicationHealth){
$CheckServer = $HealthCheck.Server
$CheckName = $HealthCheck.Check
$CheckResult = ($HealthCheck.Result).ToString()
$CheckError = $HealthCheck.Error
#Check for any Failures
if ($CheckResult -ne "Passed"){
$AlertText += "!RED!$CheckServer has failed the Replication Health Check $CheckName</br>"
$AlertCount += $AlertCount.count + 1
}
#Build Array
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -name "Name" -value $CheckServer
$obj | Add-Member -MemberType NoteProperty -Name "Check" -Value $CheckName
$obj | Add-Member -MemberType NoteProperty -Name "Result" -Value $CheckResult
$obj | Add-Member -MemberType NoteProperty -Name "Error" -Value $CheckError
$ResultsData += $obj
}
}
}
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Name"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "Backup status"
$Comment = "This module checks when each of the databases were last backed up"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
$Now = [DateTime]::Now
#Thresholds
[int]$LastBackupMax = 48 #Hours
[int]$LastBackupWarning = 24 #Hours
[int]$FullBackupMax = 14 #Days
[int]$FullBackupWarning = 7 #Days
#Create an Array and run query
$ResultsData = @()
$AllDBs = @()
$LastBackup = @{}
$Ago = @()
# Add results into the array
foreach ($Server in $ExchangeServers){
if ($Server.IsMailboxServer -eq $True){
$MailboxDBs = @(Get-MailboxDatabase -server $Server -status | Where {$_.MountedOnServer -eq ($Server.fqdn)})
$PublicFolderDBs = @(Get-PublicFolderDatabase -server $Server -status)
$AllDBs = $MailboxDBs + $PublicFolderDBs
foreach ($DB in $AllDBs){
#Get all back up information
if ($DB.IsMailboxDatabase -eq $true) {$DBType = "Mailbox"}
if ($DB.IsPublicFolderDatabase -eq $true) {$DBType = "Public Folder"}
if ($DB.LastFullBackup -eq $null -and $DB.LastIncrementalBackup -eq $nul){
$LastBackup.time = "Never"
$LastBackup.type = "Never"
[string]$Ago = "Never"
}
elseif ($DB.LastFullBackup -lt $DB.LastIncrementalBackup){
$LastBackup.time = $DB.LastIncrementalBackup
$LastBackup.type = "Incremental"
[int]$Ago = ($Now - $LastBackup.time).Totalhours
$Ago = "{0:N0}" -f $Ago
}
elseif ($DB.LastIncrementalBackup -lt $DB.LastFullBackup){
$LastBackup.time = $DB.LastFullBackup
$LastBackup.type = "Full"
[int]$Ago = ($Now - $LastBackup.time).Totalhours
$Ago = "{0:N0}" -f $Ago
}
#Check for Circular Logging
if ($DB.CircularLoggingEnabled -eq $True) {
$CircularLoggingEnabled="Yes"
}
else {
$CircularLoggingEnabled = "No"
}
#Days since last full backup
[int]$Age = ($Now - $DB.LastFullBackup).TotalDays
$Age = "{0:N0}" -f $Age
#Check age of last backup
if ($Ago -ge $LastBackupMax){
$AlertText += "!RED!The last backup for $DB.name has not run for $Ago hours. </br>"
$AlertCount += $AlertCount.count + 1
}
elseif ($Ago -ge $LastBackupWarning){
$AlertText += "!ORANGE!The last backup for $DB.name has not run for $Ago hours. </br>"
$WarningCount += $WarningCount.count + 1
}
#Check age of last Full backup
if ($Age -ge $FullBackupMax){
$AlertText += "!RED!The last backup for $DB.name has not run for $Age days. </br>"
$AlertCount += $AlertCount.count + 1
}
elseif ($Age -ge $FullBackupWarning){
$AlertText += "!ORANGE!The last backup for $DB.name has not run for $Age days. </br>"
$WarningCount += $WarningCount.count + 1
}
#Build Array
$obj = New-Object PSobject
$obj | Add-Member NoteProperty -Name "Server/DAG" -Value $DB.MasterServerOrAvailabilityGroup
$obj | Add-Member NoteProperty -Name "Database" -Value $DB.name
$obj | Add-Member NoteProperty -Name "Database Type" -Value $DBType
$obj | Add-Member NoteProperty -Name "Last Backup Type" -Value $LastBackup.type
$obj | Add-Member NoteProperty -Name "Hours Since Last Backup" -Value $Ago
$obj | Add-Member NoteProperty -Name "Last Backup Time Stamp" -Value $LastBackup.time
$obj | Add-Member NoteProperty -Name "Days Since Full Backup" -Value $Age
$obj | Add-Member NoteProperty -Name "Circular Logging Enabled" -Value $CircularLoggingEnabled
$ResultsData += $obj
}
}
}
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Server/DAG","Database"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "Disk and Database Statistics"
$Comment = "This module checks database statistics and vailable disk space."
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
$Now = [DateTime]::Now
#Thresholds
[int]$MaxMailboxes = 1000 #Total Count
[int]$WarningMailboxes = 500 #Total Count
[int]$MaxDBSize = 1000 #GB
[int]$WarningDBsize = 750 #GB
[int]$MinFreeDisk = 5 #%
[int]$WarningFreeDisk = 10 #%
#Create an Array and run query
$ResultsData = @()
$AllDBs = @()
# Add results into the array
foreach ($Server in $ExchangeServers){
if ($Server.IsMailboxServer -eq $True){
$MailboxDBs = @(Get-MailboxDatabase -server $Server -status | Where {$_.MountedOnServer -eq ($Server.fqdn)})
foreach ($DB in $MailboxDBs){
#Database Stats
$DBStats = get-mailboxdatabase $DB -status | Select-object databasesize,AvailableNewMailboxSpace,EdbFilePath,LogFolderPath
[INT]$DBSizeGB = ($DBStats.databasesize).ToGB()
[INT]$DBSizeMB = ($DBStats.databasesize).ToMB()
[INT]$WSSizeGB = ($DBStats.AvailableNewMailboxSpace).ToGB()
#Mailbox Stats
$MBXStats = get-mailboxdatabase $DB | Get-Mailbox -Resultsize Unlimited | select-object count
[INT]$MBXCount = $MBXStats.count
#Archive Stats
$ArchiveStats = get-mailboxdatabase $DB | Get-Mailbox -archive -Resultsize Unlimited | select-object count
[INT]$ArchiveCount = $ArchiveStats.count
#Average Size
[INT]$AllCount = $MBXCount + $ArchiveCount
[LONG]$AvgMBXSize = $DBSizeMB / $AllCount
# Disk Statistics
$DiskStats = @()
$DiskStats = Get-WmiObject win32_logicaldisk -computername $Server | Where-Object { $_.DriveType -eq 3 } | select DeviceID,FreeSpace,Size
$DBPath = ($DBStats.EdbFilePath).ToString()
$DBDisk = $DBPath.substring(0,2)
$LogPath = ($DBStats.LogFolderPath).ToString()
$LogDisk = $LogPath.substring(0,2)
foreach ($Disk in $DiskStats){
$DiskID = $Disk.DeviceID
if ($DBDisk -eq $DiskID){
$DBDiskFree = [Math]::Round($Disk.FreeSpace/1GB, 2)
$DBDiskSize = [Math]::Round($Disk.Size/1GB, 2)
$DBDiskPercentFree = [Math]::Round($DBDiskFree / $DBDiskSize * 100)
}
if ($LogDisk -eq $DiskID){
$LogDiskFree = [Math]::Round($Disk.FreeSpace/1Gb)
$LogDiskSize = [Math]::Round($Disk.Size/1Gb)
$LogDiskPercentFree = [Math]::Round($LogDiskFree / $LogDiskSize * 100)
}
}
#Check number of mailbioxes
if ($AllCount -ge $MaxMailboxes){
$AlertText += "!RED!There is a VERY large number of mailboxes on $Server. </br>"
$AlertCount += $AlertCount.count + 1
}
elseif ($AllCount -ge $WarningMailboxes){
$AlertText += "!ORANGE!There is a large number of mailboxes on $Server. </br>"
$WarningCount += $WarningCount.count + 1
}
#Check database size
if ($DBSizeGB -ge $MaxDBSize){
$AlertText += "!RED!The database $DB is VERY large. </br>"
$AlertCount += $AlertCount.count + 1
}
elseif ($DBSizeGB -ge $WarningDBsize){
$AlertText += "!ORANGE!The database $DB is large. </br>"
$WarningCount += $WarningCount.count + 1
}
#Check Free Disk Space - Databases
if ($DBDiskPercentFree -le $MinFreeDisk){
$AlertText += "!RED!$Server database disk ($DBDisk) only has $DBDiskPercentFree% free space remaining ($DBDiskFree GB free of $DBDiskSize GB). </br>"
$AlertCount += $AlertCount.count + 1
}
elseif ($DBDiskPercentFree -le $WarningFreeDisk){
$AlertText += "!ORANGE!$Server database disk ($DBDisk) only has $DBDiskPercentFree% free space remaining ($DBDiskFree GB free of $DBDiskSize GB). </br>"
$WarningCount += $WarningCount.count + 1
}
#Check Free Disk Space - Logs
if ($LogDiskPercentFree -le $MinFreeDisk){
$AlertText += "!RED!$Server Logs disk ($LogDisk) only has $DBDiskPercentFree% free space remaining ($LogDiskFree GB free of $LogDiskSize GB). </br>"
$AlertCount += $AlertCount.count + 1
}
elseif ($LogDiskPercentFree -le $WarningFreeDisk){
$AlertText += "!ORANGE!$Server Logs disk ($LogDisk) only has $DBDiskPercentFree% free space remaining ($LogDiskFree GB free of $LogDiskSize GB). </br>"
$WarningCount += $WarningCount.count + 1
}
#Build Array
$obj = New-Object PSobject
$obj | Add-Member NoteProperty -Name "Server" -Value $Server
$obj | Add-Member NoteProperty -Name "Database" -Value $DB.name
$obj | Add-Member NoteProperty -Name "Mailbox Count" -Value $MBXCount
$obj | Add-Member NoteProperty -Name "Archive Count" -Value $ArchiveCount
$obj | Add-Member NoteProperty -Name "Avg. Mailbox Size" -Value "$AvgMBXSize MB"
$obj | Add-Member NoteProperty -Name "Database Size" -Value "$DBSizeGB GB"
$obj | Add-Member NoteProperty -Name "Whitespace" -Value "$WSSizeGB GB"
$obj | Add-Member NoteProperty -Name "Free DB Disk Space" -Value "$DBDiskPercentFree %"
$obj | Add-Member NoteProperty -Name "Free Log Disk Space" -Value "$LogDiskPercentFree %"
$ResultsData += $obj
}
}
}
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Server/DAG","Database"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "Check Mail FLow"
$Comment = "This module checks mail flow between each Mailbox server"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
#Thresholds
[int]$LatencyMax = 30 #Seconds
[int]$LatencyWarning = 10 #Seconds
#Create an Array and run query
$ResultsData = @()
# Add results into the array
foreach ($SourceServer in $ExchangeServers){
if ($SourceServer.IsMailboxServer -eq $True){
$obj = New-Object PSObject
$obj | Add-Member NoteProperty -Name "Source Server" -Value $SourceServer.name
foreach ($TargetServer in $ExchangeServers){
if ($TargetServer.IsMailboxServer -eq $True){
try {
$Result = Test-Mailflow -Identity $SourceServer -TargetMailboxServer $TargetServer -ErrorAction Stop
}
catch{
$msg = $_.Exception.Message
$AlertText += "!ORANGE!Message latency from $SourceServer to $TargetServer not tested due to an error.</br>"
$AlertText += "!ORANGE!$Msg</br>"
$WarningCount += $WarningCount.count + 1
$Result = $null
}
if ($Result){
[double]$Latency = "{0:N2}" -f $($Result.MessageLatencyTime.TotalSeconds)
$obj | Add-Member NoteProperty -Name "To $TargetServer (Secs)" -Value $Latency
}
else{
$obj | Add-Member NoteProperty -Name "To $TargetServer (Secs)" -Value "Error"
$AlertText += "!RED!Unable to run Mailflow test from $SourceServer to $TargetServer </br>"
$AlertCount += $AlertCount.count + 1
}
#Check latency Thresholds
if ($Latency -ge $LatencyMax){
$AlertText += "!RED!Message latency from $SourceServer to $TargetServer is VERY high </br>"
$AlertCount += $AlertCount.count + 1
}
elseif ($Latency -ge $LatencyWarning){
$AlertText += "!ORANGE!Message latency from $SourceServer to $TargetServer is high </br>"
$WarningCount += $WarningCount.count + 1
}
}
}
$ResultsData += $obj
}
}
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Source Server"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "Test MAPI Connectivity"
$Comment = "This module verifies server functionality for MAPI and LDAP"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
#Create an Array and run query
$ResultsData = @()
# Add results into the array
foreach ($Server in $ExchangeServers){
if ($Server.IsMailboxServer -eq $True){
$MailboxDBs = @(Get-MailboxDatabase -server $Server -status | Where {$_.MountedOnServer -eq ($Server.fqdn)})
foreach ($DB in $MailboxDBs){
$MAPIHealth = Get-MailboxDatabase $DB | Test-MapiConnectivity
foreach ($HealthCheck in $MAPIHealth){
$CheckServer = $HealthCheck.Server
$CheckDB = $HealthCheck.Database
$CheckResult = ($HealthCheck.Result).ToString()
$CheckError = $HealthCheck.Error
#Check for any Failures
if ($CheckResult -ne "Success"){
$AlertText += "!RED!$CheckServer has failed the MAPI Health Check on $CheckDB</br>"
$AlertCount += $AlertCount.count + 1
}
#Build Array
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -name "Server" -value $CheckServer
$obj | Add-Member -MemberType NoteProperty -Name "Database" -Value $CheckDB
$obj | Add-Member -MemberType NoteProperty -Name "Result" -Value $CheckResult
$obj | Add-Member -MemberType NoteProperty -Name "Error" -Value $CheckError
$ResultsData += $obj
}
}
}
}
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Server"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "Test OWA Connectivity"
$Comment = "This module verifies server functionality for Outlook Web Access"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
#Create an Array and run query
$ResultsData = @()
$URL = "https://exchange.mydomain.com.au/owa"
# Add results into the array
$OWAHealth = Test-OwaConnectivity –URL $URL -MailboxCredential $Credentials -TrustAnySSLCertificate
$CheckURL = $OWAHealth.URL
$CheckResult = ($OWAHealth.Result).ToString()
$CheckLatency = $OWAHealth.Latency
$CheckError = $OWAHealth.Error
#Check for any Failures
if ($CheckResult -ne "Success"){
$AlertText += "!RED!$CheckServer has failed the OWA Health Check</br>"
$AlertCount += $AlertCount.count + 1
}
#Build Array
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -Name "URL" -Value $CheckURL
$obj | Add-Member -MemberType NoteProperty -Name "Result" -Value $CheckResult
$obj | Add-Member -MemberType NoteProperty -Name "Latency" -Value $CheckLatency
$obj | Add-Member -MemberType NoteProperty -Name "Error" -Value $CheckError
$ResultsData += $obj
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Server"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "Test Web Services Connectivity"
$Comment = "This module verifies server functionality for Web Services (Outlook Anywhere)"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
#Create an Array and run query
$ResultsData = @()
# Add results into the array
foreach ($Server in $CASServers){
$WebHealth = Test-WebServicesConnectivity –ClientAccessServer $Server –MailboxCredential $Credentials -TrustAnySSLCertificate
foreach ($HealthCheck in $WebHealth){
$CheckServer = $Server
$CheckScenario = $HealthCheck.Scenario
$CheckResult = ($HealthCheck.Result).ToString()
$CheckLatency = $HealthCheck.Latency
$CheckError = $HealthCheck.Error
#Check for any Failures
if ($CheckResult -ne "Success"){
$AlertText += "!RED!$CheckServer has failed the Web Services Health Check</br>"
$AlertCount += $AlertCount.count + 1
}
#Build Array
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -name "Server" -value $CheckServer
$obj | Add-Member -MemberType NoteProperty -Name "Scenario" -Value $CheckScenario
$obj | Add-Member -MemberType NoteProperty -Name "Result" -Value $CheckResult
$obj | Add-Member -MemberType NoteProperty -Name "Latency" -Value $CheckLatency
$obj | Add-Member -MemberType NoteProperty -Name "Error" -Value $CheckError
$ResultsData += $obj
}
}
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Server"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "Test POP Connectivity"
$Comment = "This module verifies server functionality for POP3"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
#Create an Array and run query
$ResultsData = @()
# Add results into the array
foreach ($Server in $CASServers){
$POPHealth = Test-PopConnectivity –ClientAccessServer $Server –MailboxCredential $Credentials -TrustAnySSLCertificate
foreach ($HealthCheck in $POPHealth){
$CheckServer = $Server
$CheckScenario = $HealthCheck.Scenario
$CheckResult = ($HealthCheck.Result).ToString()
$CheckLatency = $HealthCheck.Latency
$CheckError = $HealthCheck.Error
#Check for any Failures
if ($CheckResult -ne "Success"){
$AlertText += "!RED!$CheckServer has failed the POP3 Health Check</br>"
$AlertCount += $AlertCount.count + 1
}
#Build Array
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -name "Server" -value $CheckServer
$obj | Add-Member -MemberType NoteProperty -Name "Scenario" -Value $CheckScenario
$obj | Add-Member -MemberType NoteProperty -Name "Result" -Value $CheckResult
$obj | Add-Member -MemberType NoteProperty -Name "Latency" -Value $CheckLatency
$obj | Add-Member -MemberType NoteProperty -Name "Error" -Value $CheckError
$ResultsData += $obj
}
}
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Server"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "Test IMAP Connectivity"
$Comment = "This module verifies server functionality for IMAP4"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
#Create an Array and run query
$ResultsData = @()
# Add results into the array
foreach ($Server in $CASServers){
$IMAPHealth = Test-ImapConnectivity –ClientAccessServer $Server –MailboxCredential $Credentials -TrustAnySSLCertificate
foreach ($HealthCheck in $IMAPHealth){
$CheckServer = $Server
$CheckScenario = $HealthCheck.Scenario
$CheckResult = ($HealthCheck.Result).ToString()
$CheckLatency = $HealthCheck.Latency
$CheckError = $HealthCheck.Error
#Check for any Failures
if ($CheckResult -ne "Success"){
$AlertText += "!RED!$CheckServer has failed the IMAP Health Check</br>"
$AlertCount += $AlertCount.count + 1
}
#Build Array
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -name "Server" -value $CheckServer
$obj | Add-Member -MemberType NoteProperty -Name "Scenario" -Value $CheckScenario
$obj | Add-Member -MemberType NoteProperty -Name "Result" -Value $CheckResult
$obj | Add-Member -MemberType NoteProperty -Name "Latency" -Value $CheckLatency
$obj | Add-Member -MemberType NoteProperty -Name "Error" -Value $CheckError
$ResultsData += $obj
}
}
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Server"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "Test SMTP Connectivity"
$Comment = "This module verifies server functionality for SMTP"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
#Create an Array and run query
$ResultsData = @()
# Add results into the array
foreach ($Server in $TransportServers){
$SMTPHealth = Test-SMTPConnectivity –Identity $Server
foreach ($HealthCheck in $SMTPHealth){
$CheckConnector = $HealthCheck.ReceiveConnector
$CheckBinding = $HealthCheck.Binding
$CheckEndpoint = $HealthCheck.Endpoint
$CheckResult = ($HealthCheck.StatusCode).ToString()
#Check for any Failures
if ($CheckResult -ne "Success"){
$AlertText += "!RED!$Server has failed a SMTP Health Check from $CheckConnector to $CheckEndpoint. </br>"
$AlertCount += $AlertCount.count + 1
}
#Build Array
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -Name "Receive Connector" -Value $CheckConnector
$obj | Add-Member -MemberType NoteProperty -Name "Binding" -Value $CheckBinding
$obj | Add-Member -MemberType NoteProperty -Name "Endpoint" -Value $CheckEndpoint
$obj | Add-Member -MemberType NoteProperty -Name "Result" -Value $CheckResult
$ResultsData += $obj
}
}
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Receive Connector"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "Test System Health"
$Comment = "This module analyses your environment according to best practices"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
[int]$AlertCount = 0
[int]$WarningCount = 0
# Run test and add results to XMl file
$Test = Test-SystemHealth -OutData
Set-Content -Value $Test.FileData -Path "$OutputFolder\SystemHealthOutData_$Date.xml" -Encoding Byte
if ($output -eq "OnScreen"){
$ResultsText = "System Health analysis completed. Please import the results file ($OutputFolder\SystemHealthOutData.xml) into the Best Practices Analyser tool"
}
elseif ($output -eq "Email"){
$ResultsText = "System Health analysis completed. Please import the attached XML results into the Best Practices Analyser tool"
}
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = "" # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "$OutputFolder\SystemHealthOutData_$Date.xml" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "Event Logs"
$Comment = "Event Log entries that match defined criteria"
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Create an Array and run query
$ResultsData = @()
$AlertData = @()
$WarningData = @()
#Define Event Log Queries
<#
TIP:
- Customise queries via Event Viewer > Create Custom View > Copy query string from XML tab
- Ensure to choose a time frame that matches your reporting period eg 'Last 24 Hours'
#>
$AlertXML = '<QueryList>
<Query Id="0" Path="Application">
<Select Path="Application">*[System[(Level=1 or Level=2) and TimeCreated[timediff(@SystemTime) &lt;= 86400000]]]</Select>
<Select Path="System">*[System[(Level=1 or Level=2) and TimeCreated[timediff(@SystemTime) &lt;= 86400000]]]</Select>
<Select Path="MSExchange Management">*[System[(Level=1 or Level=2) and TimeCreated[timediff(@SystemTime) &lt;= 86400000]]]</Select>
</Query>
</QueryList>'
$WarningXML = '<QueryList>
<Query Id="0" Path="Application">
<Select Path="Application">*[System[(Level=3) and TimeCreated[timediff(@SystemTime) &lt;= 86400000]]]</Select>
<Select Path="System">*[System[(Level=3) and TimeCreated[timediff(@SystemTime) &lt;= 86400000]]]</Select>
<Select Path="MSExchange Management">*[System[(Level=3) and TimeCreated[timediff(@SystemTime) &lt;= 86400000]]]</Select>
</Query>
</QueryList>'
#Add data to array
foreach ($Server in $ExchangeServers){
#Event Log Alerts
$AlertEvents = Get-WinEvent -ea SilentlyContinue -ComputerName $Server -Filterxml $AlertXML
ForEach ($LogEntry in $AlertEvents) {
if ($LogEntry.Level -eq 1){$LevelTxt = "!RED!Critical"}
elseif ($LogEntry.Level -eq 2){$LevelTxt = "!RED!Error"}
elseif ($LogEntry.Level -eq 3){$LevelTxt = "!ORANGE!Warning"}
else {$LevelTxt = "Info"}
if ($LogEntry.Message.Length -ge 75){$Msg = $LogEntry.Message.substring(0,75)}
else {$Msg = $LogEntry.Message}
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -name "Server" -value $Server
$obj | Add-Member -MemberType NoteProperty -name "Level" -value $LevelTxt
$obj | Add-Member -MemberType NoteProperty -name "Logged" -value $LogEntry.TimeCreated
$obj | Add-Member -MemberType NoteProperty -name "Source" -value $LogEntry.ProviderName
$obj | Add-Member -MemberType NoteProperty -name "ID" -value $LogEntry.ID
$obj | Add-Member -MemberType NoteProperty -name "Event Data" -value $Msg
$AlertData += $obj
$AlertCount += $AlertCount.count + 1
}
#Event Log Warnings
$WarningEvents = Get-WinEvent -ea SilentlyContinue -ComputerName $Server -Filterxml $WarningXML
ForEach ($LogEntry in $WarningEvents) {
if ($LogEntry.Level -eq 1){$LevelTxt = "!RED!Critical"}
elseif ($LogEntry.Level -eq 2){$LevelTxt = "!RED!Error"}
elseif ($LogEntry.Level -eq 3){$LevelTxt = "!ORANGE!Warning"}
else {$LevelTxt = "Info"}
if ($LogEntry.Message.Length -ge 75){$Msg = $LogEntry.Message.substring(0,75)}
else {$Msg = $LogEntry.Message}
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -name "Computer" -value $Server
$obj | Add-Member -MemberType NoteProperty -name "Level" -value $LevelTxt
$obj | Add-Member -MemberType NoteProperty -name "Logged" -value $LogEntry.TimeCreated
$obj | Add-Member -MemberType NoteProperty -name "Source" -value $LogEntry.ProviderName
$obj | Add-Member -MemberType NoteProperty -name "ID" -value $LogEntry.ID
$obj | Add-Member -MemberType NoteProperty -name "Event Data" -value $Msg
$AlertData += $obj
$WarningCount += $WarningCount.count + 1
}
}
# Results Data
$ResultsData = $AlertData + $WarningData | sort -Property "Logged"
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = "" # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
$Attachment = "" # $Attachment MUST be either UNC path or ""
############################################################################################################
# Info #
#------------------------
$Title = "ActiveSync - Device Count per User"
$Comment = "This module checks the total number of EAS devices against the maximum device limit."
$Author = "The Agreeable Cow"
$PluginDate = "09/06/2013"
$Version = "v1.0"
# 1.0 09/06/2013 The Agreeable Cow Original Build
############################################################################################################
# Main Script #
#------------------------
#Reset Counters
$AlertText = ""
$WarningText = ""
$AlertCount = 0
$WarningCount = 0
<#
TIP: The default EasMaxDevices is 10 devices per user.
Enable the $PurgeOldDevices option below to remove devices for individuals that have not connected for a specified period of time.
#>
#Thresholds
$Policy = Get-Throttlingpolicy | where {$_.IsDefault -eq $TRUE} | select-object EasMaxDevices
[int]$MaxDevices = $Policy.EasMaxDevices
[int]$AlertDevices = 0.90 * $MaxDevices #eg 0.90 * 10 will alert on 9 devices
[int]$WarningDevices = 0.70 * $MaxDevices #eg 0.70 * 10 will warn on 7 devices
[int]$ReportMinimum = 0.50 * $MaxDevices #eg 0.50 * 10 wil report on 5 or more devices
$PurgeOldDevices = $TRUE # $TRUE or $FALSE
$PurgeAge = 180 # If Alerting and $PurgeOldDevices = $TRUE, Devices that have not connected for this many days, will be removed
$EASLogFile = "$OutputFolder\PurgedEASDevices_$Date.txt"
#Create an Array and run query
$ResultsData = @()
$EASMailboxes = Get-CASMailbox -Filter {HasActiveSyncDevicePartnership -eq $True -and DisplayName -notlike "CAS_{*"} | Get-Mailbox
# Add results into the array
foreach ($Mailbox in $EASMailboxes){
$EASInfo = $Mailbox | Select-Object SamAccountName, DisplayName, PrimarySMTPAddress, @{Name="EASDeviceCount";Expression={(Get-ActiveSyncDevice -Mailbox $_.Identity).Count}}
#Get users with enough devices to report on
if ($EASInfo.EASDeviceCount -ge $ReportMinimum){
$Name = $EASInfo.DisplayName
#Get excesive devices
if ($EASInfo.EASDeviceCount -ge $AlertDevices){
#Purge old devices
if ($PurgeOldDevices -eq $TRUE){
$DevicesToPurge = Get-ActiveSyncDevice -Mailbox $Mailbox | Get-ActiveSyncDeviceStatistics | where {$_.LastSuccessSync -le (Get-Date).AddDays(-$PurgeAge)}
$RemoveCount = 0
foreach($Device in $DevicesToPurge){
$Log = $TRUE
$RemoveCount += $RemoveCount.Count + 1
$DeviceID = $Device.Identity
$Model = $Device.DeviceModel
$LastSync = $Device.LastSuccessSync
write-output ("Device Purged $Date: `t $Name, $DeviceID, $Model, $LastSync") | out-file $EASLogFile -append
Remove-ActiveSyncDevice ([string]$Device.Guid) -confirm:$false
}
#Reporting
if ($RemoveCount -ge 1){
$AlertText += "!RED!$Name has an excessive number of ActiveSync Devices. $RemoveCount device(s) purged being older than $PurgeAge days. Please see attached log. </br>"
}
else{
$AlertText += "!RED!$Name has an excessive number of ActiveSync Devices </br>"
}
}
else{
$AlertText += "!RED!$Name has an excessive number of ActiveSync Devices </br>"
}
$AlertCount += $AlertCount.count + 1
}
elseif ($EASInfo.EASDeviceCount -ge $WarningDevices){
$WarningText += "!ORANGE!$Name has a large number of ActiveSync Devices </br>"
$WarningCount += $WarningCount.count + 1
}
#Build Array
$obj = New-Object PSobject
$obj | Add-Member -MemberType NoteProperty -name "Name" -value $Name
$obj | Add-Member -MemberType NoteProperty -name "Email Address" -value $EASInfo.PrimarySMTPAddress
$obj | Add-Member -MemberType NoteProperty -name "Device Count" -value $EASInfo.EASDeviceCount
$ResultsData += $obj
}
}
# Results Text
if ($AlertText -ne $null -or $WarningText -ne $null){
$ResultsText = $AlertText + $WarningText
}
else{
$ResultsText = ""
}
# Results Data
$ResultsData = $ResultsData | sort -Property "Device Count" -Descending
# Results Alert
if ($AlertCount -ge 1){
$ResultsAlert = "Alert"
}
elseif ($WarningCount -ge 1){
$ResultsAlert = "Warning"
}
else{
$ResultsAlert = "Good"
}
############################################################################################################
# Output #
#------------------------
$OutText = $ResultsText # $OutText MUST be either $ResultsText or "" Valid $ResultsText is any text string
$OutData = $ResultsData # $OutData MUST be either $ResultsData or "" Valid $ResultsData is any data array
$OutAlert = $ResultsAlert # $OutAlert MUST be either $ResultsAlert or "" Valid $ResultsAlert are 'Good', 'Warning' or 'Alert'
if ($Log -eq $TRUE){
$Attachment = $EASLogFile # $Attachment MUST be either UNC path or ""
}
else{
$Attachment = ""
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment