Powershell – Exchange Environmental Check

Powershell – Exchange Environmental Check

I have adapted the “Modern Exchange Environment Check” from Satheshwaran Manoharan and for use on a Exchange Server 2016 environment.
Added to the already excelent script is the following

  • Section Headers
  • MailboxDB provisioning Status
  • Whitespace check
  • Exchange Log Dir Size
  • Exchange Server Drive Space
  • Mail Queue Checks
  • House Keeping of created files


I feel that this is now a more complete report of the Exchange Server environment and the servers it runs upon.

I had toyed with adding the “10 largest user Mailboxes” to the account, but this takes a considerable time to run and would be better suited to ad-hoc reporting.

[CC lang=’powershell’]
# Requires -version 2 – Runs in Exchange Management Shell

# It displays Complete Exchange Environment Information in a modern HTML. It covers only Exchange 2010 or later.

# Set Working Dir
Push-Location (Split-Path -path $MyInvocation.MyCommand.Definition -Parent)

#Add Exchange Server snapin if not already loaded

if (!(Get-PSSnapin | where {$_.Name -eq “Microsoft.Exchange.Management.PowerShell.E2010”}))
{
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction SilentlyContinue
}
Write-Progress -Activity “Date” -status “Collecting Dates info”
$Date = Get-date -ErrorAction SilentlyContinue

# —– Settings —-

#Should the Script Open the HTML File locally on Finishing the script – Say Yes – if you wish to

$Openhtmllocally = “No”

Write-Progress -Activity “Email Settings” -status “Storing Email Settings”
## —– Email —-Fill in with your details

$EmailTo = “[email protected]
$EmailFrom = “[email protected]
$EmailSubject = “Exchange Status Report $Date”
$SmtpServer = “mail.yourdomain.com”
$Date = (Get-Date -format “dd-MM-yyyy”)
$Attachment = “.\output\ModernExchangeEnvironmentReport($date).htm”

# —– Settings —-

#Collecting Environment Information
Write-Progress -Activity “Exchange Servers” -status “Collecting Exchange Servers info”
$ExchangeServers = Get-ExchangeServer -ErrorAction SilentlyContinue

Write-Progress -Activity “Mailboxes” -status “Collecting Collecting Mailboxes info”
$mailboxes = Get-mailbox -ResultSize Unlimited -ErrorAction SilentlyContinue

Write-Progress -Activity “Databases” -status “Collecting Databases info”
$Databases = Get-mailboxdatabase -Status -ErrorAction SilentlyContinue

Write-Progress -Activity “DAG” -status “Collecting DAG info”
$DAGS = Get-DatabaseAvailabilityGroup -ErrorAction SilentlyContinue

Write-Progress -Activity “DistributionGroups” -status “Collecting DistributionGroup info”
$DistributionGroups = Get-DistributionGroup -ResultSize Unlimited -ErrorAction SilentlyContinue

Write-Progress -Activity “DynamicDistributionGroups” -status “Collecting DynamicDistributionGroup info”
$DynamicGroups = Get-DynamicDistributionGroup -ResultSize Unlimited -ErrorAction SilentlyContinue

Write-Progress -Activity “MailContacts” -status “Collecting MailContacts info”
$MailContacts = Get-MailContact -ResultSize Unlimited -ErrorAction SilentlyContinue

Write-Progress -Activity “Public Folder” -status “Collecting Public Folder Mailboxes info”
$PFmailboxes = Get-mailbox -PublicFolder -ResultSize Unlimited -ErrorAction SilentlyContinue

Write-Progress -Activity “SendConnectors” -status “Collecting SendConnectors info”
$SendConnectors = Get-SendConnector -ErrorAction SilentlyContinue

Write-Progress -Activity “Accepted Domains” -status “Collecting Accepted Domains info”
$AcceptedDomains = Get-AcceptedDomain -ErrorAction SilentlyContinue

Write-Progress -Activity “OrgAdmins” -status “Collecting OrgAdmins info”
$OrgAdmins = Get-RoleGroupMember “Organization Management” -ErrorAction SilentlyContinue

#Applying Initial CSS For the HTML
Write-Progress -Activity “ModernExchangeEnvironmentReport” -status “Applying CSS”
$head = @”
Volume Report

“@

#Create Tables in split so that users can remove or add tables easily.
$start = @”

“@
Write-Progress -Activity “ModernExchangeEnvironmentReport” -status “Writing Enviroment Initial Info”
$Table1 =@”

Exchange Environment Report

No.Exchange Servers No.Databases No.Mailboxes No.PublicFolder Mailboxes No.DistributionGroups No.DynamicGroups No.Contacts No.DAG No.Domains No.OrgAdmins Date
$($ExchangeServers.count) $($Databases.count) $($mailboxes.count) $($PFmailboxes.count) $($DistributionGroups.count) $($DynamicGroups.count) $($MailContacts.count) $($DAG.count) $($AcceptedDomains.count) $($OrgAdmins.count) $($Date)

“@

Write-Progress -Activity “ExchangeServers” -status “Writing ExchangeServers info”
$Table2 =
foreach ($server in ($ExchangeServers))
{“

“}

$table2close = @”

Exchange Servers Roles Edition Site Version Operating System SendConnectors Used
$($server.name) $($server.serverrole) $($server.edition) $($server.site.name) $($server.AdmindisplayVersion -replace “version”,”) $($windows2012above = ((Get-WmiObject -ComputerName $server.name -class Win32_OperatingSystem -ErrorAction SilentlyContinue) | Where-Object{($_.Version -like “6.*”) -or ($_.version -like “10.*”) -and ($_.Version -notlike “6.1.*”) -and ($_.version -notlike “6.0.*”)}).version.count
if ($windows2012above -eq 1)
{(Get-CimInstance -ComputerName $server.name Win32_OperatingSystem).caption -replace “Microsoft Windows Server”,”})
$(($SendConnectors | Where-Object{$_.SourceTransportServers -match “$($server.name)”}).identity.name)

“@

Write-Progress -Activity “Databases” -status “Writing Database info”
$Table3 =@”

Mailbox DB Stats

“@

$Table3data = foreach ($Database in $Databases)
{
$dbsize = $($Database.databasesize -replace “\(.*”,”)

$dbWhitespace = $($database.AvailableNewMailboxSpace -replace “\(.*”,”)

$Mountstatus = $($Database.Mounted)

if($Mountstatus -eq “True”)
{
$Mcolor = “#99FF66”
}
else
{
$Mcolor = “#FF5050”
}

$ContentIndexStatus = $((Get-MailboxDatabaseCopyStatus “$($database.name)\$($database.servername)”).contentindexstate)
if($ContentIndexStatus -eq “Healthy”)
{
$color = “#99FF66”
}
else
{
$color = “#FF5050”
}


}

$table3close = @”

Mailbox Databases Mounted ContentIndex DBSize WhiteSpace Mailboxes Master Group Database copies MbxRetention.Days ItemRetention.Days CircularLogging Provisioning Suspended Provisioning Disabled Last Full Backup
$($Database.name) $($Database.Mountedonserver) $ContentIndexStatus $dbsize $dbWhitespace $((get-mailbox -database $Database).count) $($Database.MasterServerOrAvailabilityGroup) $($Database.databasecopies.identity.name) $($Database.MailboxRetention.days) $($Database.DeletedItemRetention.days) $($Database.CircularLoggingEnabled -replace “False”,”No” -replace “True”,”Yes”) $($database.IsSuspendedFromProvisioning -replace “False”,”No” -replace “True”,”Yes”) $($database.IsExcludedFromProvisioning -replace “False”,”No” -replace “True”,”Yes”) $($database.lastfullbackup)

“@

if($dags.count -ge 1)
{
Write-Progress -Activity “Dag” -status “Writing DaG info”
$Table4 =@”

DAG statistics

“@

$Table4data = foreach ($dag in $dags)
{“


}

$table4close = @”

DAG Name Member Servers DAC Mode Witness server Witness Directory
$($DAG.name) $($dag.servers.name) $($dag.DatacenterActivationMode) $($dag.Witnessserver) $($dag.WitnessDirectory)

“@

Write-Progress -Activity “Dag” -status “Writing DaG Replication info”
$Table5 =@”

Server Statistics

“@

Write-Progress -Activity “Dag” -status “Writing DaG info”

$Table5data = foreach ($dag in $dags)
{
foreach ($member in $((Get-DatabaseAvailabilityGroup $dag).servers.name))
{
$replstatus = Test-ReplicationHealth $member
for($i=0;$i -lt $replstatus.count;$i++)
{
if($replstatus.result[$i].value -eq “Passed”)
{
$Rcolor = “#99FF66”
}
else
{
$Rcolor = “#FF5050”
}


}
}
}

$table5close = @”

Server Check Result Error
$(($replstatus).Server[$i]) $(($replstatus).Check[$i]) $($replstatus.Result[$i].value) $(($replstatus).Error[$i])

“@
}
else
{
Write-Progress -Activity “Dag” -status “Skipping DaG – No DAG Found”
}

$MailqueueTb= @”

Mail Queues

“@

Write-Progress -Activity “Mail Queues” -status “Perusing the Mail Queues”

Foreach ($server in $ExchangeServers){
$MailQueues += Get-Queue -server $server | Select-Object NextHopDomain, Status, @{Label=”Message Count”;Expression={if ($_.MessageCount -lt 30){“#div_gre”+ $_.MessageCount}else{“#div_red”+ $_.MessageCount}}}, Identity
}
$MailQueues = $MailQueues|ConvertTo-Html -Fragment
$file = “.\MailQueues.txt”
$MailQueues | SC $file
(GC $file|Select-Object -Skip 3)|SC $file
$MailQueues = GC $file
$MailQueues = $MailQueues -replace ‘

Next Hop Domain Status Message Count Freespace (GB)
#div_red’, ‘


$MailQueues = $MailQueues -replace ‘

#div_gre’, ‘


Remove-Item $file

$table6= @”

Server Drive Space Statistics

“@

Write-Progress -Activity “Drive Space” -status “Writing Drive Space info”
$threshold=’90’
Write-Verbose -Message “===================================`n= DISK SPACE CHECKS =`n= Checks the size of volumes, including =`n= mount points, and shows those with =`n= less than $threshold% free. =`n============================================”
$thresholdMsg = “

Drive(s) listed below have less than $threshold% free space. Drives above this threshold will not be listed.


$onlinelist = @()
$offlinelist = @()
$results = @()
Write-Verbose -Message ‘Performing ping test on servers …’
$exchangeservers|ForEach-Object -Process {
if(Test-Connection -ComputerName $_ -Quiet -Count 2)
{
Write-Verbose -Message “`t$_ is up”
$onlinelist += $_
}
else
{
Write-Warning -Message “`t`t`t`t$_ is down”
$offlinelist += $_
}
}

if($offlinelist -ne $null)
{
$ofs = ‘,’
$offlineMsg = “

The following servers are offline: $offlinelist


$ofs = ‘ ‘
}
ForEach($server in $onlinelist)
{
Try
{
Write-Verbose -Message “Gathering drive info on $server”
$row = Get-WmiObject -ComputerName $server -Class Win32_Volume `
|
Where-Object -FilterScript {
$_.DriveType -eq ‘3’
} `
|
Where-Object -FilterScript {
$_.Capacity -gt 0
} `
|
Where-Object -FilterScript {
($_.freespace/$_.capacity)*100 -lt $threshold
} `
|
Select-Object -Property SystemName, Name, @{
n = ‘Capacity (GB)’
e = {
‘{0:n2}’ -f ($_.capacity/1gb)
}
}, @{
n = ‘FreeSpace (GB)’
e = {
‘{0:n2}’ -f ($_.freeSpace/1gb)
}
}, @{
n = ‘PercentFree’
e = {
if(‘{0:n2}’ -f (($_.freespace/$_.capacity)*100) -lt 10)
{
“#div_red”+'{0:n2}’ -f ($_.freespace/$_.capacity*100)
}
elseif(‘{0:n2}’ -f (($_.freespace/$_.capacity)*100) -lt 15)
{
“#div_ora”+'{0:n2}’ -f ($_.freespace/$_.capacity*100)
}
elseif(‘{0:n2}’ -f (($_.freespace/$_.capacity)*100) -lt 20)
{
“#div_yel”+'{0:n2}’ -f (($_.freespace/$_.capacity)*100)
}
elseif(‘{0:n2}’ -f ($_.freespace/$_.capacity*100) -gt 20)
{
“#div_gre”+'{0:n2}’ -f (($_.freespace/$_.capacity)*100)
}
}
}
}
Catch [System.Exception]
{
Write-Warning -Message $_.Exception.Message
}
$results += $row
}
$results = $results|ConvertTo-Html -Fragment
$file = “.\results.txt”
$results | SC $file
(GC $file|Select-Object -Skip 3)|SC $file
$results = GC $file
$results = $results -replace ‘

Server Volume Capacity (GB) Freespace (GB) Percent Free
#div_yel’, ‘


$results = $results -replace ‘

#div_ora’, ‘


$results = $results -replace ‘

#div_red’, ‘


$results = $results -replace ‘

#div_gre’, ‘


Remove-Item $file

$table6close=@”

“@

Write-Progress -Activity “Log Sizes” -status “Writing Log Size info”
$table7=@”

Exchange Log Sizes

“@

$trupath = @()
$databases | ForEach-ObJect{
$logpath = $_.LogFolderPath.ToString()
$logserver = $_.Servername.ToString()
$trupath += $logpath -replace “C:\\”, “\\$logserver\c$\”
}

$table7data=ForEach($pat in $trupath){
$size = “{0:N2} MB” -f ((GCI $pat -recurse |Measure-Object -Property Length -Sum -ErrorAction Stop).Sum / 1MB)


}

$table7close=@”

Log Path Size MB
$Pat $size

“@

$complete = @”


“@

#Combining All Tables.

$alltables = “$start $Table1 $Table2 $table2close $Table3 $Table3data $table3close $Table4 $Table4data $table4close $Table5 $Table5data $table5close $mailqueuetb $mailqueues $table6 $table6close $results $Table7 $Table7data $table7close ”

$Combine = ConvertTo-Html -Head $head -Body $alltables

#Saving HTML File To the local C Drive – You can modify as per your wish.
$html += $Combine
$html > $Attachment

#open the HTML File Locally
If($Openhtmllocally -eq “yes”)
{
Invoke-Item “$Attachment”
}
else
{
Write-Progress -Activity “Open HTML” -status “Settings – Do not Open”
}
#Sending Email Message

#Send-mailmessage -to $EmailTo -from $EmailFrom -subject $EmailSubject -SmtpServer $SmtpServer -Body “Please see attached” -BodyAsHtml -Attachments $Attachment -ErrorAction SilentlyContinue

# House Keping
GCI .\output\ | Where-Object -FilterScript {
$_.LastWriteTime -lt (Get-Date).AddDays(-6)}|Remove-Item
[/CC]

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to Top