Exchange PowerShell Filtering Examples

When writing Exchange PowerShell scripts it is very useful to target specific machines to either query or set their properties.  Thus the ability to generate a query that effectively targets the correct machines is a very good thing to have!

The reason I'm posting this is that I see a lot of people manually specify a list of servers, and then iterate through the list which typically looks like this:

$ExchangeServers = "Exch-1", "Exch-2", "Exch-3"
ForEach ($Server In $ExchangeServers)
# The code to do something goes here…..
#  I would indent these lines if Live Writer would allow it…
# Oh well, it’s not a perfect world…

This is all good and fine if you have three servers.  What if you have three hundred? Man, that would be a gargantuan sized variable and really horrible to maintain!

In those cases we want to work the server list out on the fly, and then iterate through the collection.  Let’s look at some sample code that allows us to focus upon certain types and locations of servers.

Select Only Specific Roles

Starting with  simple example, let’s pull in a list of all the CAS servers in the organisation.  Then for the remaining Exchange 2010/2007 roles.  You will note that we have built in cmdlets for discovering each of these roles in  a nice easy fashion:

Show CAS Servers


Show HUB Transport Servers


Show Mailbox Servers


Show Unified Messaging Servers


Well, that was  good start!  But let’s say that we want to then filter this list further.  What if we want to then get a specific version of CAS?


Select Only Exchange 2010 CAS

In the previous example we successfully used the Get-ClientAccessServer cmdlet to retrieve a list of all CAS servers.  So it should be simple to then just add the version information to this cmdlet as Get-Member does show us that there is a version parameter.  For more information on Get-Member and other PowerShell fundamentals please check this series of articles out.


Oh, smeg!  All of the versions are the same.  What to do??

To be able to see the version information of a server, we need to use the Get-ExchangeServer cmdlet.  There are other reasons for using this as well that we will get into at the end of the post.

In this example let’s select only Exchange 2010 CAS Servers.  To do this we need to check that they are Version 14 (Exchange 2010 is E14).  We shall save the Name parameter into the $CASServers variable, and sort it.  Note that we are using Get-ExchangeServer as we can see the AD site information with that cmdlet.  Get-ClientAccessServer does not return site information.

This collection will be only CAS servers.  Note though that, depending upon your requirements, you have to filter this more as it will include every CAS from every corner of your Exchange organisation.  We shall address that concern later in the post!


$CASServers = Get-ExchangeServer | Where-Object {$_.IsClientAccessServer -Eq $true -and $_.AdminDisplayVersion -Match "^Version 14" }  |  Select Name | Sort-Object


In the above PowerShell code we are using the –Match operator.  You will note that the “^” symbol is within the string that is being searched for.  The ^ character indicates that this is the location where the string begins.  This is part of regular expression searches, and you can read more about this here.

My personal preference is to always sort these collections so when reviewing output, since the data is then in a predictable order and that makes it much quicker and easier to analyse.

One other thing to note when looking at the Exchange 2007 and 2010 version strings.  They will not increment when a RU is installed.  Only an Exchange 2007 and Exchange 2010 Service Pack is designed to advance the build number.  Exchange 2013 will increment the build number for each CU that is installed.  This is discussed in great detail here.


Select Only Exchange 2007 CAS

Taking the previous example, it is a simple task to then change this so that we look for the Exchange 2007 version information which is “8.”.  At this time all of your Exchange 2007 servers must be on Service Pack 3, with an up to date rollup as well.  We could then hard code the search to look for only SP3 builds of Exchange 2007 which would be “8.3”, but let’s leave it open to search all versions.


$CASServers = Get-ExchangeServer | Where-Object {$_.IsClientAccessServer -Eq $true -and $_.AdminDisplayVersion -Match "^Version 8" }  |  Select Name | Sort-Object



Select Only Exchange 2010 HUB Transport

$E14HUBServers = Get-ExchangeServer | Where-Object {$_.IsHubTransportServer -Eq $true -and $_.AdminDisplayVersion -Match "^Version 14" }  |  Select Name | Sort-Object



Select Only Exchange 2010 Mailbox

$E14MailboxServers = Get-ExchangeServer | Where-Object {$_.IsMailboxServer -Eq $true -and $_.AdminDisplayVersion -Match "^Version 14" }  |  Select Name | Sort-Object



Let’s now switch this up a little and make some more complicated queries!


Select Only Exchange 2010 CAS In A Specific AD Site

As mentioned above, there will be times that you do not want to get every single CAS server in the organisation.  Sometimes you only want those is  a particular AD site.  Remember that all CAS in a site should be configured the same, as you cannot control to what CAS a particular user is referred to and thus the configuration needs to be  the same to ensure a consistent user experience.

In this example we want to get a collection of just the Exchange 2010 servers that exist in a specific AD site called Edinburgh.

$E14CASServers = Get-ExchangeServer | Where-Object {$_.AdminDisplayVersion -match "^Version 14" -and $_.ServerRole -Match "ClientAccess" -and ($_.Site -match "Edinburgh") } | Sort Name

The trick as you see here, is the multiple “-And” statements.  This makes sure that each of the elements must evaluate to $True for it to be considered as part of the collection.  Should any part of a given server evaluate to $False then it will not be present in the collection.


Select Only Exchange 2010 CAS In Multiple AD Sites

In the above example we leverage multiple  “-And” statements to generate the required logic.  In the example here we then add to this by using an “-OR” statement.  For a server to be included in the collection it could be in AD SiteA or AD SiteB.  In the example below the sites are called Edinburgh and Aberlour.  Please ensure that this does not wrap:


$E14CASServers = Get-ExchangeServer | ?{$_.AdminDisplayVersion -match "^Version 14" -and $_.ServerRole -Match "ClientAccess" -and ($_.Site -match "Edinburgh" -or $_.Site -match "Aberlour") } | Sort Name


Select Only Exchange 2003 Servers

This will be a very handy command to ensure that all of your Exchange 2003 servers have been removed by the 8th of April 2014!


$Exchange2003Servers = Get-ExchangeServer  | where {$_.AdminDisplayVersion -match "6.5"}


  For this and the other examples we can get a count of the servers in a couple of ways.


$Exchange2003Servers  | Measure-Object








Select Specific Mailbox Databases

If you have a few hundred mailbox databases, then you will have developed a naming scheme for them to indicate which DAG, continent and mailboxes are contained therein.

Exchange Get-MailboxDatabase Select Wildcard

To see databases that contain a particular string we can use our familiar wildcard search character:


Get-MailboxDatabase *04*


This is shown in the above example.  We want to see databases that contain the phrase “04”.  The same can be done for many other objects in Exchange.


Select Specific Mailboxes

For mailbox filtering examples, this is covered in great detail in this previous post.




Rhoderick Milne [MSFT]

Leave a Reply

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