Monitoring Exchange 2007 / 2010 with Powershell (Part 1)

by [Published on 11 Aug. 2011 / Last Updated on 11 Aug. 2011]

This article will detail how, using PowerShell you can construct a basic script that when scheduled via the Windows Task Scheduler can monitor your Exchange 2007/2010 servers and notify you of when critical issues occur.

If you would like to read the other parts in this article series please go to:


The ability to know what is happening on your Exchange Servers quickly and accurately is one of the corner stones of effective Exchange Server Administration. Whether you are an admin of a large or small Exchange installation, you cannot afford to be without critical monitoring data – which is not just re-active; but proactive.

Traditional Exchange Monitoring

Traditional Exchange monitoring within production environments is usually handled via dedicated, separately licensed monitoring products, such as Microsoft SCOM (System Centre Operations Manager), eNOW Mailscape.

In the case of SCOM – this tends to be aimed at the Medium to Enterprise organisation market where its feature set extends much beyond just Exchange monitoring. The product gives you basic Monitoring for Windows based servers out of the box, and extended monitoring for products like Exchange is supplied in the form of “Management Packs”.

The Exchange Management pack for SCOM will give any administrator a wealth of options and facets to monitor and configure within their Exchange installation, and is considered by many the de facto monitoring product for Exchange (as well as a number of other Microsoft products).

However, it should also be noted that SCOM does represent additional licensing costs, and requires quite a lot of planning and configuration in order to get the most of it – which, due to the cost and complexity tends to lend it more to the larger Exchange installations.

Other Exchange monitoring products such as Mailscape have had a reasonable amount of success within small to medium sized enterprises (and some large scale installations) as (taking Mailscape as an example) are purely Exchange focussed, are competitively licensed and are simple to install and use.

Aside from cost implications almost all 3rd party Exchange monitoring software is “Agent based” – e.g. a small item of software is installed on your Exchange severs in order to collect data. Whereas there is little performance impact to using such Agents – it does add another small layer of installation and updates to your Exchange as the Monitoring product changes.

Now, please don’t think for one second that I am making a case against using 3rd party monitoring products – if you have the requirement, money and the time I would say that they are an essential accompaniment to your Exchange infrastructure and should be planned in to any deployment.

However, there is one common aspect to all Exchange based monitoring products which I think sometimes gets overlooked – which is that since Exchange 2007 and the implementation of PowerShell – 99% of all monitoring tasks which the mainstream 3rd party products facilitate can be accomplished by your own scripts.

This is of course not to say that you could go out tomorrow and write something in PowerShell that does all of what SCOM and other products do – but, for the creative minds amongst you whom have limited budgets the fact that PowerShell exists and is relatively easy to learn – means that you can code solutions that take care of the core monitoring tasks.

For example:
One common performance counter which is included within System Centre Operations Manager is the MSExchangeIS RPC Averaged Latency counter (it is also freely available via the Performance monitor tool – however SCOM gives you the ability to report and notify on it).

To illustrate the point that I made above, you can access the value of this counter directly from within PowerShell (the sample given below uses the Get-Counter cmdlet which is included in version 2 of PowerShell) – like so;

$perf=Get-Counter-ComputerNamelocalhost-Counter"\MSExchangeIS\RPC Averaged Latency"-sampleinterval 5 | Foreach-Object{ $_.CounterSamples[0].CookedValue }

if ($perf-gt 0){

       Write-Host"High Latency found"


What I have done above is to use 4 lines of PowerShell code to return the value of the Exchange performance counter over a sample period of 5 seconds. I have then compared it to a threshold value of 0 (in production this would be obviously higher) and then if the threshold is invoked I display a message (which could be changed to send an e-mail).

Defining a monitoring script

It is always cool to just start coding – but, when designing something that might end up in production - it pays to define what you want the script to do.

For the purpose of this series I have determined that the script will perform the following actions:

  • Get the names of your Environments Exchange Servers from a text file

It is entirely possible to detect the names of your Exchange servers using the get-ExchangeServer cmdlet

  • Ping each Exchange Server to determine if they are online
  • Determine the roles which are resident on each server to perform tests on
  • Check the disk space on each Exchange Server
  • Check the Application Event log for the last 10 Exchange related messages
  • Check the CPU Load factors against a defined threshold
  • Check the memory load factors against a defined threshold
  • Check the Size of Mailbox Databases
  • Checks the status of Mailbox Server Backups
  • Checks to see if all Mailbox Databases and Public Folders are mounted
  • Checks the size of Message Queues against a predefined threshold
  • Checks the Web Services configuration on Client Access Servers
  • Checks the status of key services for each role
  • e-mails a defined admin when a problem is found

I would like to point out at this stage, that this script that we will produce over in these four parts is comparatively simple and really designed to demonstrate what can be achieved. There are better ways to accomplish some of the tasks which I have detailed above which you are encouraged to seek out – and indeed also develop the script to expand its functionality.

Constructing the script

As the series goes on the foundation of what is provided here will grow into the complete script. The way I tend to code scripts is to have a single entry point function (in this case the “pingServers” function– which then calls all others sequentially to perform tasks.

The script will require PowerShell 2 to be installed on your Exchange Servers in order to function as it uses some PS2 specific CMDLets.

I will start with a number of Global Variables which reside at the top of the script and should be customised to suite your own personal environments.

I will then move on to define the following functions:

  • The e-Mail notification function
  • The Ping function

Global Constants

The following are the global constants which will be used by the script.

The first two constants are used to get the list of Exchange Servers for monitoring from a text file into a constant which is then used by the script to provide the server names.

The second constant is used to hold either the IP address, NETBIOS name or FQDN of the SMTP server that will be used by the script to relay e-mail notifications.

In terms of the “ExchangeServer.txt” file – this should be located on a path that is accessible to the script and each line within the file should contain the NETBIOS, IP or FQDN of the Exchange Servers that you wish to monitor.

# Get our list Exchange Servers and configure mail

$ExServers=Get-Content"<Path to >ExchangeServers.txt File"

$SMTPHost="<Insert your SMTP Server Here>"

The next 7 constants are used to set the thresholds that the script will notify the admin about should they be breeched:

# Set global Constants

$DBSizeThreshold= 200                    # Max size of Mailbox DB in MB

$PDBSizeThreshold= 200                   # Max size of Public Folder in MB

$lastBackupThreshhold= 1                 # Allowed elapsed time since last backup in days

$DiskspacePercentageFree= 10                    # Low disk space threshold in %

$QueueMessageUpperLevel= 200             # Max Number of Messages in any Queue

$MemoryThreshold= 800                    # Lowest amount of MB Free

$CPU_UpperLeverPercentage= 20            # Highest Max CUP Utilisation

Notification Function

Now that we have our constants defined we need the ability to notify the admin when one or more of the thresholds are breeched. I have chosen the primary notification method to be via SMTP mail.

In order to accomplish this I have defined a PowerShell function entitled “SMTPAlertMessage

The SMTPAlertMessage function accepts two mandatory parameters ($strSubject,$strBody) – these naturally refer to the message subject and body respectively.

The mandatory parameters, are added to an array “$sParams” – which is used to construct the required parameters for the “Send-MailMessage” cmdlet. You should note that we have also used the Global Constant $SMTPHost for the SMTP Server parameter of Send-MailMessage – and elected to send all e-mail from the function as HTML:


$sParams= @{                       

Subject =$strSubject

Body =$strBody

From =""

To =""

SmtpServer =$SMTPHost


Send-MailMessage @sParams -BodyAsHtml


Ping Function

Before the script sends an e-mails or performs any Role tests on the servers which are located in the ExchangeServers.txt file – it is wise to “Ping” them to ensure that they are reachable on the network.

The function “pingServers” gets the server names from the ExchangeServers.txt and using a “Foreach” loop cycles through each server and using the “Win32_PingStatus” WMI class attempts to Ping them – getting the result of the Ping (the status code) into a variable called $pingStat.

If the StatusCode result is “0” then the server has replied – and we are in a position to call the following functions (which will be developed in the next part of this series):

  • Check_CPU
  • Check_Mem
  • CheckRoles

If the StatusCode is anything other than 0, the script assumes that there is a problem with the server on the network – and an e-mail message (using theSMTPAlertMessagefunction) is fired off to the administrator.


       Foreach ($exMacin$ExServers){

       $pingStat=Get-WmiObject-classWin32_PingStatus-Filter"Address = '$exMac'" | selectStatusCode

       if ($pingStat.StatusCode -eq 0){

              Write-Host"Server $exMac Replied to ping"-ForegroundColorGreen

              check_CPU     # Defined in next part

              check_Mem     # Defined in next part

              checkRoles    # Defined in next part


              Write-Host"Server $exMac did not reply to ping"-ForegroundColorRed

              $MessBody="Exchange Server: $exMac is not responding to ping requests"

              SMTPAlertMessage"Exchange Server not responding to pings"$MessBody





That completes part one of this series. We have looked at some traditional 3rd party based monitoring concepts, and at a basic level discussed some of the merits / disadvantages of using them in the context of your Exchange environment. We have also begun to construct and alternative monitoring script for Exchange using PowerShell. In the next part we will define the check_cpu, check_mem and check_roles functions.

If you would like to read the other parts in this article series please go to:

See Also

The Author — Andy Grogan

Andy Grogan avatar

Andy is currently a UK based CIO responsible for the whole IT systems strategy for a large social housing provider based in London. Prior to his current role he was Head of Technical operations for one of the largest councils in London, Technical architect for a dedicated US based Exchange consultancy.


Featured Links