Get-ActiveExchangeUsers 2.0

A while a go I wrote the inital script and post about it here. Due to my experience over the last few weeks and to meet additional requirements it was time to go over the script and extend its functionality. I thought about updating the previous post, but due to the major changes I decided to create this new post.

Update May 30, 2016:

Many thanks to fellow MCM/MCSM Thomas Stensitzki, who added some code for nicer format and preview when sending the output as e-mail:



The script will query multiple performance counters from Exchange servers in a given AD site.

Default counter collection

MSExchange RpcClientAccess\User Count

Shows the number of users connected to the service.

MSExchange RpcClientAccess\Connection Count

Shows the total number of client connections maintained.

RPC/HTTP Proxy\Current Number of Unique Users

Shows the number of unique users currently connected to a back-end server via RPC/HTTP.

MSExchange OWA\Current Unique Users

Shows the number of unique users currently logged on to Outlook Web App. This value monitors the number of unique active user sessions, so that users are only removed from this counter after they log off or their session times out.

MSExchange ActiveSync\Current Requests

Shows the number of HTTP requests waiting to be assigned to a thread.

W3SVC_W3WP(*msexchangeservicesapppool)\Active Requests

Shows the number of active EWS requests.

MSExchange MapiHttp Emsmdb\Active User Count

Active User Count is the number of unique users that have shown some activity in the last 2 minutes.

MSExchange MapiHttp Emsmdb\Connection Count

Connection Count is the total number of client connections maintained.

W3SVC_W3WP(*MSExchangeMapiFront*)\Active Requests

Shows the number of active requests of the MSExchangeMapiFrontEndAppPool.

W3SVC_W3WP(*MSExchangeMapiMailbox*)\Active Requests

Shows the number of active requests of the MSExchangeMapiMailboxAppPool.

Web Service(_Total)\Current Connections

Shows the number of current total connections to the IIS.

Web Service(_Total)\Maximum Connections

Shows the max number of total connections to the IIS.

Netlogon(_Total)\Semaphore Timeouts

Shows the number of Semaphore Timeouts since the last start of the Netlogon service.

Most of those counters are described here and here. Why should you also have an eye on the Netlogon counter? If you have a larger environment and/or multiple forests you will agree that this is a good idea after you read this. In short: the counter should be always zero. If not you might have a bottleneck and consider to tweak MaxConcurrentAPI.

Updated version

As described above the script collects by default the performance counters previously mentioned. One of the major changes is that the format of the output is not anymore a formated list (Format-Table). It will return an object. It will also show the list of Exchange server found only when you use the common parameter -Verbose. Since the object has more than 10 properties and in case you want to use Format-Table or Format-List, you need to specify the parameter -Property * to get all properties. Personally I like Out-GridView.

Here how it looks like


Let’s have a closer look. Within this AD site you can see different versions and roles of Exchange:


When you look at the values for MAPI FE AppPool and MAPI BE AppPool you can see that the CAS role only have values for the FE, but not for the BE. And of course the Exchange 2010 CAS don’t have any values. I also added the ratio between the BE and FE. This is an important topic when it comes to fault tolerance and HA, but this will be topic of a different post.

Switch Summary

When you use the summary switch only a few main performance counters will be collected and summed up to a total number


The interesting part here is that the overall number of active requests reported for the MAPI application pools are almost equal. Why only almost? For instance think of those request on the FE component, which are not authenticated and never make it to the BE.

Switch -HTTPProxyAVGLatency

By using this switch the following counters will be collected:

MSExchange HttpProxy(autodiscover)\Average ClientAccess Server Processing Latency
MSExchange HttpProxy(eas)\Average ClientAccess Server Processing Latency
MSExchange HttpProxy(ecp)\Average ClientAccess Server Processing Latency
MSExchange HttpProxy(ews)\Average ClientAccess Server Processing Latency
MSExchange HttpProxy(mapi)\Average ClientAccess Server Processing Latency
MSExchange HttpProxy(oab)\Average ClientAccess Server Processing Latency
MSExchange HttpProxy(owa)\Average ClientAccess Server Processing Latency
MSExchange HttpProxy(owacalendar)\Average ClientAccess Server Processing Latency
MSExchange HttpProxy(powershell)\Average ClientAccess Server Processing Latency
MSExchange HttpProxy(rpchttp)\Average ClientAccess Server Processing Latency

All of those reflect the average latency (ms) of CAS processing time (does not include time spent proxying) over the last 200 requests.


As the HttpProxy component only exist on servers starting with version 2013 no legacy servers are listed.

Note: The values for Outlook Anywhere are always high(at least in this environmet), but user experience is still good. I haven’t found an explanation for the values so far.

Switch HTTPProxyOutstandingRequests

By using this switch the following counters will be collected:

MSExchange HttpProxy(autodiscover)\Outstanding Proxy Requests
MSExchange HttpProxy(eas)\Outstanding Proxy Requests
MSExchange HttpProxy(ecp)\Outstanding Proxy Requests
MSExchange HttpProxy(ews)\Outstanding Proxy Requests
MSExchange HttpProxy(mapi)\Outstanding Proxy Requests
MSExchange HttpProxy(oab)\Outstanding Proxy Requests
MSExchange HttpProxy(owa)\Outstanding Proxy Requests
MSExchange HttpProxy(owacalendar)\Outstanding Proxy Requests
MSExchange HttpProxy(powershell)\Outstanding Proxy Requests
MSExchange HttpProxy(rpchttp)\Outstanding Proxy Requests

Those counters show the number of concurrent outstanding proxy requests and should be monitored closely.


Here you can see that some servers report a high value. This is an issue I have seen with multiple performance counters. Recycling the application pool helps to have the affected servers triggering a reload of those counters.

Note: Keep in mind that recycling application pools affects client connectivity!

Switch HTTPProxyRequestsPerSec

By using this switch the following counters will be collected:

MSExchange HttpProxy(autodiscover)\Proxy Requests/Sec
MSExchange HttpProxy(eas)\Proxy Requests/Sec
MSExchange HttpProxy(ecp)\Proxy Requests/Sec
MSExchange HttpProxy(ews)\Proxy Requests/Sec
MSExchange HttpProxy(mapi)\Proxy Requests/Sec
MSExchange HttpProxy(oab)\Proxy Requests/Sec
MSExchange HttpProxy(owa)\Proxy Requests/Sec
MSExchange HttpProxy(owacalendar)\Proxy Requests/Sec
MSExchange HttpProxy(powershell)\Proxy Requests/Sec
MSExchange HttpProxy(rpchttp)\Proxy Requests/Sec

If you some performance issue this is a good point to look into it as those counters show the number of proxy requests processed each second.

Switch E2EAVGLatency

By using this switch the following counters will be collected:

MSExchangeIS Client Type(administrator)\RPC Average Latency
MSExchangeIS Client Type(airsync)\RPC Average Latency
MSExchangeIS Client Type(availabilityservice)\RPC Average Latency
MSExchangeIS Client Type(momt)\RPC Average Latency
MSExchangeIS Client Type(owa)\RPC Average Latency
MSExchangeIS Client Type(rpchttp)\RPC Average Latency
MSExchangeIS Client Type(webservices)\RPC Average Latency
MSExchangeIS Client Type(outlookservice)\RPC Average Latency
MSExchangeIS Client Type(simplemigration)\RPC Average Latency
MSExchangeIS Client Type(contentindexing)\RPC Average Latency
MSExchangeIS Client Type(eventbasedassistants)\RPC Average Latency
MSExchangeIS Client Type(transport)\RPC Average Latency
MSExchange RpcClientAccess\RPC Averaged Latency
MSExchange MapiHttp Emsmdb\Averaged Latency

I picked those counters to see the latency and also possible end-user impact.


Switch TimeInGC

By using this switch the following counters will be collected:

.NET CLR Memory(w3w*)\% Time in GC
.NET CLR Memory(w3*)\Process ID
W3SVC_W3WP(*)\Active Requests


This is besides the HTTPProxyOutstandingRequests one of the most important switch, when it comes to performance issues. The goal is to get an idea how long a worker process spent time in GC(garbage collection) instead of responding to client requests. In order to find the correct counter for each worker you need to collect 2 additional counters. The script is doing this and when you use the -Verbose parameter it will report the process ID and the name of the worker. This makes life easier if you want to check those important counters with perfmon and don’t want to spent time for finding the right counter. For each protocoll the average, if you used the -MaxSamples switch, and the maximum value will be return. If you didn’t define the -MaxSamples the average equals the maximum value.

Where can I find the script?

You can download the script here Get-ActiveExchangeUsers.ps1

What parameters are available?



ADSite here you can define in which ADSite is searched for Exchange server. If omitted the current AD site will be enumerated.
Summary switch to get a summary of main counters
HTTPProxyAVGLatency collects the name related counters
HTTPProxyOutstandingRequests collects the name related counters
HTTPProxyRequestsPerSec collects the name related counters
E2EAVGLatency here you can define in which ADSite is searched for Exchange server
TimeInGC collects the name related counters for Exchange related protocols
SpecifiedServers you can specify one or multiple server within an AD site, if you don’t want to query all
MaxSamples the script utilze the CmdLet Get-Counter, which supports this parameter in order to specify the number of samples to collect. The default is one. If you specify a higher value the average across all samples will be returned.
SendMail switch for sending the result as CSV file
From the FromAddress for sending the e-mail
Recipients list of one or multiple recipients
SmtpServer the SMTP server to use

I hope this helps you to get a better understanding and troubleshooting(if needed) of your environment.

Feedback is always more than welcome!


18 thoughts on “Get-ActiveExchangeUsers 2.0

  1. Pingback: How many users are connected to Exchange per protocol? | The clueless guy

  2. Just some cosmetics… The screenshot shows a table output, but the FT has been commented in the script, so a FL output is generated. 🙂


    • Hey Thomas,
      you mean the TimeInGC? Due to the verbose there is an output like FL. Out-GridView shows it as a table. But there is an inconsitency: I’m forcing a FT for the summary…:P


  3. Pingback: exchange stuff may 2016 | 503 5.0.0 polite people say HELO

  4. Question. Using a domain admin account, that is local admin, and performance monitor user, it returns the servers, but all zeros in verbose mode. what have i missed? Thoughts?


  5. Hi,

    I think you should add the following line in your script
    #Requires -Version 3.0

    because it returns 0 for all value in Exchange Management Shell Exchange 2010 (Powershell 2.0)

    In PowerShell 2.0, $ArrayVariable.Property –> $null
    In PowerShell 3.0+, $ArrayVariable.Property –> an array of Property value

    In order to get it working on PowerShell 2.0, you have to replace everywhere (i.e. with $RPC)
    ([math]::Round(($RPC.CookedValue | measure -Average).Average))
    ([math]::Round(($RPC | Select-Object -ExpandProperty CookedValue | measure -Average).Average))



  6. to get it working on PowerShell 2.0, you also need to replace
    ForEach ($Sample in $CounterStats.CounterSamples | ? {$_.Path -match $Server})
    ForEach ($Sample in ($CounterStats | Select-Object -ExpandProperty CounterSamples | ? {$_.Path -match $Server}))

    Without this correction, $CounterStats.CounterSamples return null when MaxSamples is greater than 1.



  7. Pingback: Exchange performance:Garbage Collection | The clueless guy

  8. Very useful tool on my english exchange server. But unfortunately we also have a German exchange server with the german parameters. Do you have this Get-ActiveExchangeUsers.ps1 script in German?


      • Counters name is not different in PS but the folders from Exchange are different.

        I found this commands to show the current users:

        Get-Counter “\MSExchange OWA\Aktuelle eindeutige Benutzer” -ComputerName EXSVR01
        Get-Counter “\MSExchange RpcClientAccess\Anzahl Benutzer” -ComputerName EXSVR01
        Get-Counter “\MSExchange ActiveSync\Aktuelle Anforderungen” -ComputerName EXSVR01
        Get-Counter “\MSExchangeImap4(*)\Aktuelle Verbindungen” -ComputerName EXSVR01
        Get-Counter “\MSExchangePop3(*)\Aktuelle Verbindungen” -ComputerName EXSVR01


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s