by , last updated August 22, 2022, in

Identifying MS Teams Application Instances & Counting App Starts

Microsoft Teams is a web application that needs a browser as a runtime environment. In order to keep things simple – at the expense of disk space – the Teams installation package contains not only the actual web app but also all components that are needed to run it, including Chromium. When you launch Teams, you’re really launching the Chromium browser, which then executes the embedded Teams web app. Teams’ browser-based architecture presents challenges when you want to count the number of Teams instances that are running or when you need to find out how many instances of Teams have been started. This article presents multiple ways to determine accurate application usage data.

Note: this article is about Microsoft Teams 1.x. Its main executable is Teams.exe. The Teams app included in Windows 11 is architecturally different. Its main executable is Msteams.exe.

Multi-Process Architecture

As I’ve said before, the browser is an OS for web applications. Teams comes bundled with its own OS; therefore, Teams’ underlying architecture is the multi-process architecture of Chromium. When you launch Teams, you’re not starting a single Teams.exe process but a whole plethora of them. This is visualized nicely in uberAgent ESA’s Process Tree dashboard:

Teams Process Tree

Let’s examine in detail what happens when MS Teams is launched from the Start Menu.

  1. When a user launches Teams from the Start Menu, Explorer.exe executes the target of the Teams Start Menu shortcut: C:\Users\USERNAME\AppData\Local\Microsoft\Teams\Update.exe --processStart "Teams.exe"
  2. The initial Teams process to be started is Update.exe which – presumably – checks for available updates and the launches the main Teams.exe process.
  3. The main Teams process starts several additional Teams.exe processes, some of which persist for the entire lifetime of the applications, while others are more short-lived.

Teams Process Hierarchy Levels

As a Chromium variant, Teams has two process hierarchy levels:

  1. One main (browser) process: it launches helper processes as required.
  2. Many helper processes: these isolate individual tabs, extensions, GPU code, etc.

As a rule, all helper processes are started by the main process. In the screenshot above, you can see that each of the 13 Teams.exe child processes has the same parent process: the Teams.exe instance with the process ID 3792.

Teams Process Types

Let’s take a closer look at the command line arguments the various Teams.exe processes are started with. By slightly modifying the Splunk search utilized in the uberAgent ESA’s Process Tree dashboard we get the following table:

As we can see in the screenshot above, the main Teams.exe process doesn’t have any command line arguments. The helper processes, on the other hand, all have a --type= argument.

Note: the Chromium project doesn’t document the command line arguments in general and the valid process types specifically very well, but we can put two and two together. We can find all command line switches in the source code file content_switches.cc. Valid process types are listed in process_type.cc.

Techniques for Identifying Teams Instances

With the information presented above, we can develop multiple techniques to identify and count instances of the Teams application (as opposed to instances of the Teams.exe process). Please note that these techniques are based on empirical research and may not always give perfectly accurate results. Test for yourself which technique (or combination of techniques) works best for you.

Update.exe Started From the Teams Installation Directory

This technique makes use of the observed behavior that the Teams Start Menu link does not point to Teams.exe but to Update.exe.

uberAgent ESA uAQL Query

Look for process startup events with the following properties:

Process.Name == "Update.exe" and Process.CommandLine like "%--processStart \"Teams.exe\""

Note: I’m using uAQL here for multiple reasons:

Splunk SPL Search in uberAgent Events

Search Splunk for uberAgent events with the following SPL search:

index=`uberAgent_index` sourcetype=uberAgent:Process:ProcessStartup ProcName=Update.exe ProcCmdline="*--processStart \"Teams.exe\""
Splunk Search in uberAgent’s Accelerated Data Model

Search uberAgent’s accelerated data model in Splunk:

| pivot `uA_DM_Process_ProcessStartup` Process_ProcessStartup
   latest(AppName) as "App name"
   latest(AppVersion) as "App version"
   latest(_time) as StartTime
   filter ProcName is "Update.exe"
   filter ProcCmdline is "*--processStart \"Teams.exe\""
   splitrow ProcName as "Process name"
   splitrow host as Host
   splitrow ProcUser as "User name"
   splitrow StartupTimeS
| eval "Start time" = strftime (strptime (StartTime, "%Y-%m-%dT%H:%M:%S.%Q%z"), "%Y-%m-%d %H:%M:%S")
| table
   "Start time" "Host" "User name" "App name" "App version" "Process name"
| sort -"Start time"

Parent Process is not Teams.exe

This technique makes use of the fact that the Teams helper processes are child processes of Teams.exe, whereas the main Teams process is a child process of anything but Teams.exe.

uberAgent ESA uAQL Query

Look for process startup events with the following properties:

Process.Name == "Teams.exe" and Parent.Name != "Teams.exe"

Note: please see the note on uAQL above.

Splunk SPL Search in uberAgent Events

Search Splunk for uberAgent events with the following SPL search:

index=`uberAgent_index` sourcetype=uberAgent:Process:ProcessStartup ProcName=Teams.exe ProcParentName!="Teams.exe"
Splunk Search in uberAgent’s Accelerated Data Model

Search uberAgent’s accelerated data model in Splunk:

| pivot `uA_DM_Process_ProcessStartup` Process_ProcessStartup
   latest(AppName) as "App name"
   latest(AppVersion) as "App version"
   latest(_time) as StartTime
   filter ProcName is "Teams.exe"
   filter ProcParentName isNot "Teams.exe"
   splitrow ProcName as "Process name"
   splitrow host as Host
   splitrow ProcUser as "User name"
   splitrow StartupTimeS
| eval "Start time" = strftime (strptime (StartTime, "%Y-%m-%dT%H:%M:%S.%Q%z"), "%Y-%m-%d %H:%M:%S")
| table
   "Start time" "Host" "User name" "App name" "App version" "Process name"
| sort -"Start time"

Command Line Does Not Contain Type Parameter

This technique makes use of the observed behavior that the command line of Teams helper processes contains a --type= parameter, whereas the main Teams process’ command line does not contain such a parameter.

While testing this technique, I found one case where a Teams.exe process launched a full new instance of Teams. Apparently, Teams detected an issue while starting and relaunched itself. The parent process of the relaunched main Teams process had the distinctive command line: "C:\Users\helge\AppData\Local\Microsoft\Teams\current\Teams.exe" --type=relauncher --- "C:\Users\helge\AppData\Local\Microsoft\Teams\current\Teams.exe".

Of the techniques presented in this section, only this current technique includes relaunched instances of Teams.

uberAgent ESA uAQL Query

Look for process startup events with the following properties:

Process.Name == "Teams.exe" and not Process.CommandLine like "%--type=%"

Note: please see the note on uAQL above.

Example from uAQL Studio

Splunk SPL Search in uberAgent Events

Search Splunk for uberAgent events with the following SPL search:

index=`uberAgent_index` sourcetype=uberAgent:Process:ProcessStartup ProcName=Teams.exe ProcCmdline!="*--type=*"
Search Result Sample

Splunk Search in uberAgent’s Accelerated Data Model

Search uberAgent’s accelerated data model in Splunk:

| pivot `uA_DM_Process_ProcessStartup` Process_ProcessStartup
   latest(AppName) as "App name"
   latest(AppVersion) as "App version"
   latest(_time) as StartTime
   filter ProcName is "Teams.exe"
   filter ProcCmdline isNot "*--type=*"
   splitrow ProcName as "Process name"
   splitrow host as Host
   splitrow ProcUser as "User name"
   splitrow StartupTimeS
| eval "Start time" = strftime (strptime (StartTime, "%Y-%m-%dT%H:%M:%S.%Q%z"), "%Y-%m-%d %H:%M:%S")
| table
   "Start time" "Host" "User name" "App name" "App version" "Process name"
| sort -"Start time"
Search Result Sample

MS Teams Application Start Count and Startup Duration

If you’ve made it this far, you have all the techniques for advanced Microsoft Teams application startup and usage analytics. A typical use case would be to determine the number of application starts along with the application startup duration. The following Splunk searches show how to collect that information based on the third technique presented above. It should not be difficult to adjust the searches to the other MS Teams application identification techniques.

Splunk SPL Search in uberAgent Events

index=`uberAgent_index` sourcetype=uberAgent:Process:ProcessStartup ProcName=Teams.exe ProcCmdline!="*--type=*"
| stats
   count as "Start count"
   median(StartupTimeMs) as "Median startup duration [ms]"
   min(StartupTimeMs) as "Min. startup duration [ms]"
   max(StartupTimeMs) as "Max. startup duration [ms]"
   by HwModel
| rename HwModel as "Hardware model"

Splunk Search in uberAgent’s Accelerated Data Model

| pivot `uA_DM_Process_ProcessStartup` Process_ProcessStartup
   count(Process_ProcessStartup) as EventCount
   latest(StartupTimeMs) as StartupTimeMs
   latest(HwModel) as HwModel
   filter ProcName is "Teams.exe"
   filter ProcCmdline isNot "*--type=*"
   splitrow host as Host
   splitrow ProcUser as "User name"
   splitrow StartupTimeS
| stats
   count(EventCount) as "Start count"
   median(StartupTimeMs) as "Median startup duration [ms]"
   min(StartupTimeMs) as "Min. startup duration [ms]"
   max(StartupTimeMs) as "Max. startup duration [ms]"
   by HwModel

Results: Teams Start Duration and Start Count Grouped by Hardware Model

Both Splunk searches above yield the same result: a table that lists the MS Teams startup duration (min, median, max) and the application start count by hardware model:

Take a look at the uberAgent documentation for a detailed list of all fields that it collects as part of the application startup metrics.

Previous Article Windows Terminal as Standard User With Dedicated Admin Account
Next Article Windows Installer Errors 2503 & 2502: Called RunScript when not marked in progress & Called InstallFinalize when no install in progress