Teams Presence und Office IM API

"Wie kann ich den Präsenzstatus in Teams abfragen". Diese Frage habe ich mir schon häufiger gestellt. In Skype for Business konnte ich eine COM-API nutzen aber in Teams gibt es das so erst mal nicht. Neben dem Weg per Graph API können Sie alternative Wege suchen.

Teams does not use COM at all and never will. We plan to support presence APIs in Microsoft Graph bit do not have a date to share
Quelle: https://stackoverflow.com/questions/56865704/com-object-for-teams-client-microsoft-office-uc

Get notified of presence changes – the Microsoft Graph presence subscription API is now available in public preview
https://developer.microsoft.com/en-us/microsoft-365/blogs/get-notified-of-presence-changes-the-microsoft-graph-presence-subscription-api-is-now-available-in-public-preview/

Graph

Weiter unten stelle ich noch weitere APIs zum Zugriff auf Teams und Presence vor. Seit Dezember 2019 gibt es aber die ersten Funktionen den Präsenzstatus von Team über die Graph-API zu erfragen.

Es ist aber noch viel zu tun, z.B. den eigenen Status zu setzen, Benachrichtigungen (z.B. Anruf) zu erhalten

Bei den Berechtigungen gib es aktuell im Feb 2020 zu Presence nur folgende Berechtigungen, die auch noch durch einen Administrator gewährt werden müssen

Das wird aber sicher die Zukunft werden.

Office API (Microsoft.Office.Uc.dll)

Anscheinend nutzt Office immer noch diese API aber ich würde darauf nicht mehr neu entwickeln sondern Graph nutzen.

Wer sich den Teams Client for Windows anschaut, findet in den Einstellungen die folgende Option:

Damit schalten sie in Outlook aber auch Word, Excel und Co die Schnittstelle von Lync/Skype auf Teams um und in Outlook wird die Präsenzanzeige mit Teams verbunden. Ich sehen also die Präsenz des Teams-Teilnehmers im gleichen Tenant aber auch per Federation und kann über den Weg auch einen "Chat" oder einen VoIP-Anruf starten.

Was da im Hintergrund passiert, beschreibt Microsoft eigentlich ganz schön auf seiner Webseite

To enable this integration with Office, an IM client application must implement a set of interfaces that Office provides to connect to it. The APIs for this integration are included in the UCCollborationLib namespace that is contained in the Microsoft.Office.UC.dll file, which is installed with versions of Office 2013 that include Lync / Skype for Business. The UCCollaborationLib namespace includes the interfaces that you must implement to integrate with Office.
Quelle: Integrating IM applications with Office https://docs.microsoft.com/en-us/office/client-developer/shared/integrating-im-applications-with-office

Weiter im Dokument steht genau, wie sich Office dann an die Applikation anbindet.

  1. Lesen der Default IM App aus "HKEY_CURRENT_USER\Software\IM Providers\DefaultIMApp"
  2. Prüfen, ob die App läuft "HKEY_CURRENT_USER\Software\IM Providers\%AppName%\UpAndRunning=2"
  3. Ermittel des ProzessID aus "Computer\HKEY_CURRENT_USER\Software\IM Providers\Teams\ProcessId"
  4. Anbinden als "Out of Band COM-Process" über "CoCreateInstance"

So sieht ein Auszug aus meiner Registrierung aus:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\IM Providers]
"DefaultIMApp"="Teams"

[HKEY_CURRENT_USER\Software\IM Providers\Communicator]
"UpAndRunning"=dword:00000002
"ProcessId"=dword:00002bd8

[HKEY_CURRENT_USER\Software\IM Providers\EasyLy]
@=""
"IsFirstRun"=dword:00000000

[HKEY_CURRENT_USER\Software\IM Providers\Lync]
"ProcessId"=dword:00002bd8
"UpAndRunning"=dword:00000002

[HKEY_CURRENT_USER\Software\IM Providers\Teams]
"PreviousDefaultIMApp"="Lync"
"ProcessId"=dword:0000384c
"UpAndRunning"=dword:00000002

An dem Zeitpunkt war "Teams" die "DefaultIMApp" und die Zeile ""UpAndRunning"=dword:00000002" zeigt an, dass Teams mit der ""ProcessId"=dword:0000384c" gelaufen ist. Die Information kann natürlich einfach auch per PowerShell abgefragt werden.

Get-ChildItem "HKCU:Software\IM Providers\"
Get-Item "HKCU:Software\IM Providers\Teams\"

Per Powershell ist dann auch der Prozess dazu schnell gefunden:

get-process -Id 14412 | fl *

Name                       : Teams
Id                         : 14412
PriorityClass              : Normal
FileVersion                : 1.2.00.10954
HandleCount                : 1970
WorkingSet                 : 109744128
PagedMemorySize            : 116072448
PrivateMemorySize          : 116072448
VirtualMemorySize          : 1220177920
TotalProcessorTime         : 00:09:28.3281250
SI                         : 1
Handles                    : 1970
VM                         : 2204538400768
WS                         : 109744128
PM                         : 116072448
NPM                        : 86096
Path                       : C:\\AppData\Local\Microsoft\Teams\current\Teams.exe
Company                    : Microsoft Corporation
CPU                        : 568,328125
ProductVersion             : 1.2.00.10954
Description                : Microsoft Teams
Product                    : Microsoft Teams
__NounName                 : Process
BasePriority               : 8
ExitCode                   :
HasExited                  : False
ExitTime                   :
Handle                     : 4280
SafeHandle                 : Microsoft.Win32.SafeHandles.SafeProcessHandle
MachineName                : .
MainWindowHandle           : 41029646
MainWindowTitle            : UCLabor | Microsoft Teams
MainModule                 : System.Diagnostics.ProcessModule (Teams.exe)
MaxWorkingSet              : 1413120
MinWorkingSet              : 204800
Modules                    : {System.Diagnostics.ProcessModule (Teams.exe), System.Diagnostics.ProcessModule
                             (ntdll.dll), System.Diagnostics.ProcessModule (KERNEL32.DLL),
                             System.Diagnostics.ProcessModule (KERNELBASE.dll)...}
NonpagedSystemMemorySize   : 86096
NonpagedSystemMemorySize64 : 86096
PagedMemorySize64          : 116072448
PagedSystemMemorySize      : 957848
PagedSystemMemorySize64    : 957848
PeakPagedMemorySize        : 132956160
PeakPagedMemorySize64      : 132956160
PeakWorkingSet             : 178851840
PeakWorkingSet64           : 178851840
PeakVirtualMemorySize      : 1279320064
PeakVirtualMemorySize64    : 2204597542912
PriorityBoostEnabled       : True
PrivateMemorySize64        : 116072448
PrivilegedProcessorTime    : 00:03:50.9531250
ProcessName                : Teams
ProcessorAffinity          : 255
Responding                 : True
SessionId                  : 1
StartInfo                  : System.Diagnostics.ProcessStartInfo
StartTime                  : 15.05.2019 23:17:00
SynchronizingObject        :
Threads                    : {3328, 16276, 29388, 22428...}
UserProcessorTime          : 00:05:37.3750000
VirtualMemorySize64        : 2204538400768
EnableRaisingEvents        : False
StandardInput              :
StandardOutput             :
StandardError              :
WorkingSet64               : 109744128
Site                       :
Container                  :

Damit bleibt aber immer noch die Frage, wie man an ein passenden COM-Objekt kommt Aus dem PowerShell-Magazin habe ich dann einen Code-Schnipsel angepasst, um nach COM-Objekten zu suchen:

Get-ChildItem HKLM:\Software\Classes -ErrorAction SilentlyContinue `
| Where-Object { $_.PSChildName -like '*teams*' -and (Test-Path -Path "$($_.PSPath)\CLSID") } `
| Select-Object -ExpandProperty PSChildName
Get-ChildItem HKLM:\Software\Classes -ErrorAction SilentlyContinue `
| Where-Object { $_.PSChildName -like '*teams*' } `
| Select-Object -ExpandProperty PSChildName

Aber Treffer habe ich bei mir keine gehabt. Anscheinend ist das eine COM-Schnittstelle, die so nicht auffindbar ist. Nun will ich natürlich keine eigene API bereitstellen, um in Office eine Präsenz-Anzeige bereit zu stellen. Das wäre dann eher etwas für Unify, Avaya, Estos u.a. Aber wenn Office (Outlook, Word, Excel) diese API nutzen um in ihren Applikationen eine Präsenzanzeige und vielleicht mehr anzuzeigen, dann ist das auch für mich interessant. Es wäre ja eine Client-API, mit der ich per Skript z.B. den eigenen Präsenzstatus oder auch den Status anderer Teilnehmer abfragen könnte.

Client API

Leider gibt es in Teams keine echte Client-API. Aktuell können Sie maximal per "SendKey" entsprechende Tasten und damit auch die Hotkeys an Teams senden aber keine Daten erhalten oder gar interagieren. Insofern ist auch die Nutzung per Zusatztastaturen beschränkt.

Es gibt aber einen UserVoice-Vorschlag, für den Sie abstimmen können.

Mit einer reinen API auf dem Client könnte ein sehr einfacher Weg für Drittprodukte eröffnet werden, z.B. auch für eigene Tastaturen

Microsoft.OfficeUC.dll

In dem Zuge ist auch die DLL "Microsoft.OfficeUC.dll" in meinen Fokus gerückt. Leider konnte ich mittels "Depends.exe" nicht ermitteln, welche Funktionen und Klassen Sie bereit stellt. Allerdings gibt es eine Dokumentation, die auf einige Bestandteile referenziert. Allein auf meinem PC gibt es auch jede Menge Versionen davon, da viele Programme diese DLL einfach mitbringen.

Der Versuch diese DLL einfach mal in VBA als Verweis zu addieren, ist aber auch schief gelaufen.

Auch hier haben aber meine stümperhaften Versuche noch nicht zum Erfolg geführt.

PresenceAddinInstaller: Uc.win32.tlb und Uc.tlb

Wenn sie sich das Teams Setup-Log anschauen, dann gibt es einen interessanten Abschnitt mit dem Prefix "PresenceAddinInstaller":

2020-04-12 21:28:45> PresenceAddinInstaller: 
     Copying C:\Users\ADMIN\AppData\Local\Microsoft\Teams\current\resources\assets\tlb\Uc.tlb to 
     C:\Users\ADMIN\AppData\Local\Microsoft\TeamsPresenceAddin
2020-04-12 21:28:45> PresenceAddinInstaller: 
    Copying C:\Users\ADMIN\AppData\Local\Microsoft\Teams\current\resources\assets\tlb\Uc.win32.tlb to 
    C:\Users\ADMIN\AppData\Local\Microsoft\TeamsPresenceAddin
2020-04-12 21:28:45> PresenceAddinInstaller: check if UC TypeLib points to current\resources\assets\tlb\Uc.tlb
2020-04-12 21:28:45> PresenceAddinInstaller: Registering UC Typelib WIN32 under HKCU...
2020-04-12 21:28:46> PresenceAddinInstaller: UC Typelib WIN32 successfully registered to 
    C:\Users\ADMIN\AppData\Local\Microsoft\TeamsPresenceAddin\Uc.win32.tlb under HKCU!
2020-04-12 21:28:46> PresenceAddinInstaller: Registering UC Typelib WIN64 under HKCU...
2020-04-12 21:28:46> PresenceAddinInstaller: UC Typelib WIN64 successfully registered to 
    C:\Users\ADMIN\AppData\Local\Microsoft\TeamsPresenceAddin\Uc.tlb under HKCU!

Teams scheint hier eine "TLB"-Datei" ins Benutzerprofil zu kopieren und zu registrieren.

Eine Suche nach den Dateinamen in der Registrierung hat keine Treffer auf COM-Klassen geliefert. Ich habe dann mit "Strings" (Sysinternals) mir mal die Namen in der UC.TLB ausgeben lassen und damit im Internet gesucht. Gelandet bin ich wieder bei Verweisen auf das Assembly: Microsoft.Office.Uc (in Microsoft.Office.Uc.dll)

Die gleiche TLB-Datei wird auch von Plenoms Busylight-Software angesprochen. Insofern kann diese Schnittstelle von Clients genutzt werden, um den Status einer lokalen Teams Instanz zu ermitteln.

Auch ein GitHub-Projekt "LyncPwn" von 2012 nutzt schon diese Schnittstellen, um z.B. eine "AutoreplyAgent" zu bauen.

https://GitHub.com/sadegs/Sky/tree/master/LyncPwn/LyncPwn
https://GitHub.com/sadegs/Sky/blob/master/LyncPwn/LyncPwn/Main.cs

Es könnte also durchaus ein Weg zu, eigenen Status in Teams sein.

Es ist mir aktuell nur noch nicht gelungen, über ein einfaches PowerShell diese Schnittstelle anzusprechen.

Nutzung mit PowerShell

ich hoffe ja immer noch, dass ich eine API für die Abfrage eines Teams Presence finde, mit der ich dann ein "Teams Statusbild" in welcher Form auch immer bauen kann. Sei es als einfache Statusanzeigen per WLAN-LED (Siehe dazu z.B. Shelly Bulb auf Shelly IoT) pro Anwender oder ein LED-Band im Eingangsbereich oder ein LED-Weihnachtsbaum für eine Firma oder wegen mir auch ein ein Satz von per DMX gesteuerten Leuchten im Fenster jedes Mitarbeiters.

Der Weg über die COM-API von Teams zu gehen, die auch Office Applikationen nutzen, ist mir bislang nicht gelungen. Zukünftig wird sicher eine Abfrage über die Graph API der bessere Weg sein. Aber noch gibt es hier keine Roadmap für Präsenz. Und andere Wege wie z.B. MQTT sind noch viel weiter entfernt. Vielleicht finde ich ja noch einen Weg, wie ich die COM-API einfach direkt ansprechen kann. Aktuell bekomme ich noch einen Fehler wenn ich eine der beiden CSLIDs anspreche.

{A0651028-BA7A-4D71-877F-12E0175A5806}   Lync.UCOfficeIntegration  "C:\Program Files (x86)\Microsoft Office\Root\Office16\lync.exe"
{00425F68-FFC1-445F-8EDF-EF78B84BA1C7}
{424BE3CD-34AB-4F51-9C57-4341166DC8FA}  Treat as {A0651028-BA7A-4D71-877F-12E0175A5806}
$guid=New-Object Guid 'A0651028-BA7A-4D71-877F-12E0175A5806'
$typeinfo=[type]::GetTypeFromCLSID($guid)
$object=[activator]::CreateComInstanceFrom($typeinfo)
Für "CreateComInstanceFrom" und die folgende Argumenteanzahl kann keine Überladung gefunden werden: "1".

$object=[activator]::CreateComInstanceFrom($typeinfo,"")
Ausnahme beim Aufrufen von "CreateComInstanceFrom" mit 2 Argument(en): "Die Datei oder Assembly
"file:///C:\\System.__ComObject, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" oder
eine Abhängigkeit davon wurde nicht gefunden. Das System kann die angegebene Datei nicht finden."

Nah dran ist noch nicht gewonnen.

Browser-API

Dann ist mir z.B. in LinkedIn und Yammer aufgefallen, dass bei den Fotos von Personen, die auch in Teams bekannt sind, mit einem Status versehen werden. Ich kann in LinkedIn auch nach mir suchen und finde so einen Hinweis.

Bei anderen Menschen habe ich andere Statusmeldungen gefunden

Nun erwarte ich nicht, dass LinkedIn, obwohl es zu Microsoft gehört, serverseitig den Status ermittelt sondern das mein Browser machen muss.

Ich habe noch nicht ermittelt, wie der Browser oder vielleicht doch das LinkedIn Backend den Status ermittelt.

Weitere Links