≡ Menu

Determine the Number of Active Users on Exchange 2010 Client Access Servers with PowerShell

Looking for a quick way to see how many users are currently connected to each of your Client Access Servers? This might be useful if you want to get a rough idea on load distribution, or when you’re getting ready to drain stop a server in a CAS array prior to maintenance. It’s always good to know how many users might be affected by an taking a server down. The following PowerShell function will grab performance counter data from each server to determine the number of active OWA and RPC connections:

function Get-CASActiveUsers {
  [CmdletBinding()]
    param(
    [Parameter(Position=0, ParameterSetName="Value", Mandatory=$true)]
    [String[]]$ComputerName,
    [Parameter(Position=0, ParameterSetName="Pipeline", ValueFromPipelineByPropertyName=$true, Mandatory=$true)]
    [String]$Name
  )

  process {
    switch($PsCmdlet.ParameterSetName) {
      "Value" {$servers = $ComputerName}
      "Pipeline" {$servers = $Name}
    }
    $servers | %{
      $RPC = Get-Counter "\MSExchange RpcClientAccess\User Count" -ComputerName $_
      $OWA = Get-Counter "\MSExchange OWA\Current Unique Users" -ComputerName $_
      New-Object PSObject -Property @{
        Server = $_
        "RPC Client Access" = $RPC.CounterSamples[0].CookedValue
        "Outlook Web App" = $OWA.CounterSamples[0].CookedValue
      }
    }
  }
}

Just add the function to your shell session and when you run it, specify one or more server names using the -ComputerName parameter:

Get-CASActiveUsers -ComputerName cas1,cas2

The function is also written to support pipeline input, so you can pipe the Get-ClientAccessServer cmdlet to it as well:

Get-ClientAccessServer | Get-CASActiveUsers

It can take a few minutes before the values are updated as clients connect or disconnect. For example, if you compare the values returned by the function before and after opening Outlook and OWA on a couple of machines, you may notice that it can take a few minutes before the counter values reflect the changes.

37 comments… add one

  • Turbomcp April 4, 2011, 1:51 pm

    great script
    thanks
    would this work for 2007 also?

  • Mike Pfeiffer April 9, 2011, 10:54 am

    Thanks Turbo. The \MSExchange RpcClientAccess\User Count counter is only available on 2010 servers, so this function wouldn’t work when run against a 2007 server. You can use the \MSExchange OWA\Current Unique Users counter on 2007 CAS servers and try the MSExchangeIS\User Count counter on mailbox servers.

  • epper1250 April 15, 2011, 8:03 am

    Great Script!

    I’ve been trying to divine a method for determine which mailboxes/users are connected to which CAS server, when the CAS server sits behind a hardware load balancer for the CAS array. The idea being, if users are experiencing difficulty it may be beneficial to know precisely which CAS server a user is currently connected to -

    Any ideas/suggestions?

  • Mike Pfeiffer April 15, 2011, 8:29 am
  • Devon April 17, 2011, 4:17 pm

    How hard would it be to add ActiveSync & OA to this script?

  • Karsten July 26, 2011, 6:20 am

    Hi Mike, thanks for the interesting Script.

    We have a german installation of Exchange – unfortunately MS translated the counters. In german they have to be:

    $RPC = Get-Counter “\MSExchange RpcClientAccess\Anzahl Benutzer” -ComputerName $_
    $OWA = Get-Counter “\MSExchange OWA\Aktuelle eindeutige Benutzer” -ComputerName $_

  • Mike Pfeiffer July 28, 2011, 9:38 pm

    Interesting…thanks for the heads up!

  • Micha December 17, 2013, 9:23 am

    If you want to translate other Performance Counter to german, check this out:
    http://darkvoice.dyndns.org/blog/?p=140

  • BruceE September 29, 2011, 9:48 am

    When I use the switch -ComputerName the function fails. When I reviewed the code I tried -Name and that works fine.

    Still getting a lot of benefit from the Exchange 2010 class I took with you. Bought your Powershell book. I am taking the Powershell class 11/28-30/2011. I’ll bring the book to get it autographed.

  • Mike Pfeiffer October 14, 2011, 12:54 pm

    Sorry Bruce, I think I had an old version of the code that I somehow posted by mistake…Try it now.

    Thanks for buying the book, I hope you get some use out of it. I think Jason might be teaching the class that week, but I’ll be around and would be happy to sign your copy.

    Thanks!

  • Chetan Vora January 24, 2012, 12:42 am

    Hi Mike,

    Its really greate Script… We have users who is accesing mail through POP3 & IMAP & mapi & Active Sync.

    How about that? can i hv a script for that

    Thanks

  • Victor January 25, 2012, 7:25 pm

    Is it possible to list the users? I understand that would be a completely different function, as this one just does counts. I would like to be able to view what users are connected to a particular server so I can send out a maintenance message to them. “hey, log out or you will be bumped! This server is going down for maintenance” kinda thing. Thanks for the cool code!

  • Mohammad Hossain January 30, 2012, 10:47 am

    The Script is really great!
    We have users who is accesing mail through IMAP & Active Sync and outlook anywhere. How do I know how may users are accessing through IMAP?

    Thanks very much.

  • Rolf Schilling February 5, 2012, 4:07 am

    Her ar the counter for POP3 and IMAP

    $POP = Get-Counter “\MSExchangePop3(1)\Connections Current” -ComputerName
    $IMAP = get-counter “\MSExchangeImap4(1)\Current Connections” -ComputerName

  • Randy March 13, 2012, 6:12 am
  • Frank March 19, 2012, 12:15 pm

    Hi,

    thank you for this nice function. It helps me today. Great Work.

    regards,

    Frank

  • Greg May 11, 2012, 9:13 pm

    Thanks so much for this. This is so helpful.

  • mx3208 July 31, 2012, 8:25 am

    French version of counters

    $RPC = Get-Counter “\MSExchange RpcClientAccess\Nombre d’utilisateurs actifs” -ComputerName $_
    $OWA = Get-Counter “\MSExchange OWA\Utilisateurs uniques actuels” -ComputerName $_

  • Dave August 6, 2012, 9:44 am

    Strange, anytime I run this I don’t get any errors or results, but rather just goes back to a PS prompt. Saved the above PS to a .ps1 file name and run it using .\ prefix, and supplied the -computername variable, but no luck. Is there something special I’m missing as far as how the script should be created and executed? I’m running this via EMS on a 2010 CAS.

    Thanks in advance!

  • Mike Pfeiffer August 6, 2012, 12:09 pm

    Hey Dave,

    You want to dot source the script to get it loaded into the shell. For example:

    . .\script_name.ps1

    Then run the Get-CASActiveUsers function. See this for more info:
    http://www.mikepfeiffer.net/2010/06/how-to-add-functions-to-your-powershell-session/

  • Dave August 9, 2012, 8:59 am

    Thanks Mike,

    I thought I was “dot sourcing” the script, but apparently I did not fully understand the whole dot sourcing and how it relates to a function (or what a function was for that matter). I have it figured out now, and thanks for the reply!

  • Susanne August 23, 2012, 10:55 pm

    exactly what I was searching for! thanks a lot. What about the counter for Active Sync users ?

  • Rob Moritz February 14, 2013, 12:16 pm

    HOw do you change the output format? When I add in $ASY = Get-Counter “\MSExchange ActiveSync\Current Requests” -Computer $_

    I get the output as Activesync Server Outlook Web App RPC Client Access

    Is there a way so its Server Activesync Outlook Web App RPC Client Access

    It appears to be doing it alphabetically..

    Thanks,
    Rob

  • Mike Pfeiffer February 14, 2013, 2:37 pm

    The easiest way without re-writing the function or using v3 is to just pipe to select-object, for example:

    Get-CASActiveUsers -ComputerName red-exch-2010 | select-object server,activ*,out*,rpc*

    more details:
    http://technet.microsoft.com/en-us/magazine/hh750381.aspx
    http://msmvps.com/blogs/richardsiddaway/archive/2011/05/07/property-order.aspx
    http://mcpmag.com/articles/2012/12/11/pshell-order.aspx

  • Rob Moritz February 15, 2013, 10:50 am

    Thank you.. Duh I feel really stupid.. lol was trying to do it in the array!!!

  • Raj May 6, 2013, 11:29 am

    Hi Mike,
    Shouldn’t this be
    $RPC = Get-Counter “\MSExchange RpcClientAccess\ Active User Count” ??

    thanks

    Raj

  • Mike Pfeiffer May 9, 2013, 3:19 pm

    These are two very similar counters. Here they are with their descriptions:

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

    \MSExchange RpcClientAccess\User Count
    User Count is the number of users that are connected to the service.

    I wanted connected users to be taken into consideration with this function, even though they may not been seen recently as active.

  • Stacy July 15, 2013, 8:35 am

    Is there a way to modify the script to show a list of connected username’s to a specific CAS server?

  • Mike Pfeiffer July 16, 2013, 5:24 pm

    Sorry, no.

  • Stacy July 17, 2013, 12:19 pm

    I found this and it worked for me. Thought you might want to see it
    Get-LogonStatistics -Server | select username, clientname, clientversion, logontime, lastaccesstime | Export-CSV C:\CAS.csv

  • Mike Pfeiffer July 17, 2013, 12:34 pm

    ah…I thought you were asking about getting the names via perf counter since that’s what this example is about…glad you got what you needed.

  • Roys July 25, 2013, 5:17 am

    great script – tnx
    I am trying to add to it a value for real-time connections of mobile (smartphones, tablets..) and can not identify the counter.
    can you help?
    tnx
    Roy

  • Jeremy Bradshaw August 22, 2013, 8:40 am

    Thanks very much. I took your function and added it to one of my modules for quick easy use. Updated it a little bit to match the rest of my Don Jones inspired function layouts:

    function Get-CASActiveConnections {

    [CmdletBinding(DefaultParameterSetName="Pipeline")]
    param(
    [Parameter(Position=0, ParameterSetName="Pipeline", ValueFromPipelineByPropertyName=$True, Mandatory=$True)]
    [Alias("Server","ServerName","Computer","ComputerName","PSComputerName")]
    [String[]]$Name
    )
    BEGIN {
    }
    PROCESS {

    foreach ($CASServer in $Name) {
    $TrySuccess = $True
    TRY {
    $EAS = Get-Counter “\MSExchange ActiveSync\Current Requests” -ComputerName $CASServer -ErrorAction Stop
    $RPC = Get-Counter “\MSExchange RpcClientAccess\User Count” -ComputerName $CASServer -ErrorAction Stop
    $OWA = Get-Counter “\MSExchange OWA\Current Unique Users” -ComputerName $CASServer -ErrorAction Stop
    }
    CATCH {
    $TrySuccess = $False
    Write-Warning “Unable to query performance counters on “”$CASServer”””
    }
    if ($TrySuccess = $True) {

    $CASActiveConnectionsObject = [PSCustomObject][Ordered]@{
    ‘Name’=$CASServer;
    ‘RPCConnections’=$RPC.CounterSamples[0].CookedValue;
    ‘EASRequests’=$EAS.CounterSamples[0].CookedValue;
    ‘OWAconnections’=$OWA.CounterSamples[0].CookedValue;
    ‘Date’=Get-Date -Format “yyyy-MM-dd HH:mm:ss”
    }
    $CASActiveConnectionsObject.PSObject.TypeNames.Insert(0, ‘ExchangeTools.CASActiveConnections’)
    Write-Output $CASActiveConnectionsObject
    }
    }
    }
    END {
    }
    }

    And then prettied up the output with a module manifest and format.ps1xml:

    ExchangeTools.CASActiveConnections

    ExchangeTools.CASActiveConnections

    CAS server
    16

    ActiveSync requests
    20
    right

    RPC connections
    20
    right

    OWA connections
    20
    right

    Name

    EASRequests

    RPCConnections

    OWAConnections

  • Dianne October 2, 2013, 11:28 am

    Hi Mike! Great script. Is there a way I can collect and add the values from all my servers so I get the individual server count with the math at the bottom showing total users?

  • Chris Branca December 2, 2013, 1:18 pm

    old thread, still valuable, however,
    just thought i’d mention you can easily add
    $caz = $get-clientaccessserver
    then run Get-CASActiveUsers $caz

    if you’re multisite and only care about primary CAS just
    $caz = $get-clientaccessserver *northamerica* or whatever your naming convention is

  • payilagam December 4, 2013, 3:26 am

    thanks for the info. Can we get Active Client Logons in the database of the Exchange 2010 Server?

  • Anil Singh December 10, 2013, 5:35 am

    Hu Mike, Nice script. How can i see users name also for MAPI connection so i can trace which user connected with which CAS server in case F5 LB sitting before the all CAS’s

Leave a Comment