October 1, 2020

How to get Microsoft Teams main or meeting window? (Empower Teams Shortcuts with AutoHotkey)

Microsoft Teams provides hotkeys but they are only running if the target window is active. That means for example there is no "universal" hotkey to mute yourself during a meeting: you have to have the meeting window active to run it.
For running universal Teams Shortcuts from an application launcher see Teamsy or a small utility like the People Connector it would be great to have an efficient way to activate the Teams main Window or the active Teams Meeting window.
I present here my current solution - implemented in AutoHotkey.  

Get Teams Main Window

First idea for implementation was using the trick that Teams client only support a single instance and if you run the Teams.exe it will put the Teams application main window to the front.
So to catch the main window you can minimize all Teams windows and run the exe and wait for the Teams main window to be active. 
By default the Teams.exe file is located under the user appdata directory that you can build using the Username environment variable.

The drawback of this method is that the user will notice a window flicking when the windows are minimized and the main window is reset to the front.

Teams_GetMainWindow(){

TeamsMainWinId := PowerTools_RegRead("TeamsMainWinId")
If WinExist("ahk_id " . TeamsMainWinId) {
    return TeamsMainWinId
}

WinGet, WinCount, Count, ahk_exe Teams.exe
If (WinCount = 1) {
    TeamsMainWinId := WinExist("ahk_exe Teams.exe")
    RegWrite, REG_SZ, HKEY_CURRENT_USER\Software\PowerTools, TeamsMainWinId,%TeamsMainWinId%
    return TeamsMainWinId
}
TeamsExe = C:\Users\%A_UserName%\AppData\Local\Microsoft\Teams\current\Teams.exe
If !FileExist(TeamsExe) {
    return
}
If WinActive("ahk_exe Teams.exe") {
    GroupAdd, TeamsGroup, ahk_exe Teams.exe
    WinMinimize, ahk_group  TeamsGroup
} 
    
Run, %TeamsExe%
WinWaitActive, ahk_exe Teams.exe
TeamsMainWinId := WinExist("A")
RegWrite, REG_SZ, HKEY_CURRENT_USER\Software\PowerTools, TeamsMainWinId, %TeamsMainWinId%
return TeamsMainWinId

} ; eofun

I have come to a better alternative solution playing with the Acc library.
I have noticed in the AccViewer that the window name for the main window ends with | Microsoft Teams, Main Window


So a simpler solution using Acc looks like:
; Get main window via Acc Window Object Name
WinGet, id, List,ahk_exe Teams.exe
Loop, %id%
{
    hWnd := id%A_Index%
    oAcc := Acc_Get("Object","4",0,"ahk_id " hWnd)
    sName := oAcc.accName(0)
    If RegExMatch(sName,".* \| Microsoft Teams, Main Window$") {
        PowerTools_RegWrite("TeamsMainWinId",hWnd)
        return hWnd
    }
}

Get Teams current Meeting Window

Update: improved version is documented in this post.

Unfortunately unlike the browser, Teams meeting windows are not identifiable by their title. [In the browser the title ends with '(Meeting) | Microsoft Teams'.]

To workaround this you can ask the user to activate the meeting window before running the hotkey and store the window Id so that the next time - if the meeting window is available -, the user won't be asked.

Teams_GetMeetingWindow(){

TeamsMeetingWinId := PowerTools_RegRead("TeamsMeetingWinId")
If WinExist("ahk_id " . TeamsMeetingWinId) {
    return TeamsMeetingWinId
}

MsgBox, 0x31, Get Teams Meeting Window, Check that the Teams Meeting window is the last Active Teams Window.
WinGet TeamsMeetingWinId, ID, ahk_exe Teams.exe

WinGet, Win, List, ahk_exe Teams.exe
TeamsMainWinId := Teams_GetMainWindow()
Loop %Win% {
    WinId := Win%A_Index%
    If (WinId = TeamsMainWinId)
        Continue
    Else {
        TeamsMeetingWinId := WinId
        PowerTools_RegWrite("TeamsMeetingWinId",TeamsMeetingWinId)
        return TeamsMeetingWinId
    }
        
} ; End Loop
} ; eofun

This approach will not work with parallel meetings, means when you switch to another meeting and leave the previous one "On-hold".

For this reason, I have changed this approach by giving the user the opportunity to quickly validate the meeting window via a small Gui.
Teams: Select Meeting Window

From the list of displayed windows, I have excluded the main Teams window and other Teams window containing matching 1-1 chats i.e. a format like Lastname, Firstname (uid). (you might want to fine tune this if it doesn't work perfectly.)
If RegExMatch(Title,"^[^\s]*\s?[^\s]*,[^\s]*\s?[^\s]*$") or RegExMatch(Title,"^[^\s]*\s?[^\s]*,[^\s]*\s?[^\s]*\([^\s\(\)]*\)$") ; Exclude windows with , in the title (Popped-out 1-1 chat) and max two words before , Name, Firstname               

If there is only 1 window matching these criteria, it will be selected by default without prompting the user for selection. (I assume if the function is triggered, there shall be a meeting running.)

This approach is based on an AHK Gui utility WinListBox I have presented in another post.

N.B.: For both cases, I have chosen to store the Windows Id to the registry to get it stick even if the Teamsy.exe is closed like when used in command line mode.

Application Examples

Turn the video off during a meeting

WinId := Teams_GetMeetingWindow()
WinActivate, ahk_id %WinId%
SendInput ^+o ; toggle video Ctl+Shift+o

Create a Teams meeting

WinId := Teams_GetMainWindow()
WinActivate, ahk_id %WinId%
SendInput ^4; open calendar
Sleep, 300
SendInput !+n ; schedule a meeting alt+shift+n

Code

Code is available in github/ahk/Lib/Teams.ahk. The 2 functions are Teams_GetMainWindow() Teams_GetMeetingWindow()

Teams_GetMainWindow is also available in this Gist (still it requires the Acc Library)

See also

Teams Keyboard Shortcuts: Microsoft doc 

WinListBox Ahk Utility

Ahk Acc library

How to get the Microsoft Teams active meeting window with AutoHotkey? - Stack Overflow

AutoHotkey: Microsoft Teams Get active meeting window without user prompt


No comments:

Post a Comment