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.
- 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"
- The initial Teams process to be started is
Update.exe
which – presumably – checks for available updates and the launches the mainTeams.exe
process. - 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:
- One main (browser) process: it launches helper processes as required.
- 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:
- uAQL is so easy to read that it works just as well as any kind of pseudocode.
- uAQL queries can be developed & tested in the free web app uAQL Studio.
- uAQL queries can be used with uberAgent UXM Event Data Filtering and with uberAgent ESA Activity Monitoring.
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.