Get-CsPhoneNumber
Dass Lync in der Oberliga der Kommunikationsplattformen mitspielt, ist nicht mehr zu bestreiten. Die Verwaltung der Teilnehmer per PowerShell als auch per Webbrowser per Silverlight geht den meisten Administratoren recht einfach von den Fingern. Aber eine komplette Liste der Telefonnummern lässt sich mit Lync nicht einfach erstellen.
Dieses Skript nutzt NICHT die Lync Commandlets, um nacheinander alle verschiedenen Objekte zu ermitteln, sondern liest "RAW" direkt im Active Directory und findet damit auch Objekte, die vielleicht nicht ganz korrekt konfiguriert sind.
Zwar werden die wenigsten Administratoren noch ein gedrucktes Firmentelefonbuch veröffentlichen, aber es kann bei der Rufnummernplanung und zur Verhinderung von doppelten Vergaben, die dann beide Teilnehmer unerreichbar macht, hilfreich sein. Zwar versuchen die Commandlets schon doppelte Nummern zu erkennen, aber Sie übersehen dabei doch auch Endpunkte und die AD-Replikation kann auch ein falsches Spiel treiben. Eine Liste und Validierung der Einträge ist daher wünschenswert. Genau das macht dieses PowerShell-Script.
Diese Auswertung ist wichtig, da leider Lync nicht alle Fälle von doppelt vergebenen Nummern bei der Konfiguration erkennt. So kann ein Benutzer die gleiche TelURI bekommen wie ein CommonAreaPhone. Lync warnt nicht nur können dann beide nicht mehr per Rufnummer angerufen werden.
Objekte
In Lync gibt es eine ganze Menge von Objekten, die eine Telefonnummer haben können. Seit Lync kann ein Anwender sogar eine zweite "private" Nummer haben, die entsprechend mit berücksichtig werden muss. Folgende Objekte konnte ich bislang mit einer Rufnummer identifizieren:
Object | Partition | Beschreibung |
---|---|---|
Benutzer Telefon |
Domain |
Ein normaler Lync Anwender mit seiner primären Nummer im Feld msRTCSIP-Line |
Benutzer Private Line |
Domain |
Ein normaler Lync Anwender mit seiner privaten Nummer im Feld msRTCSIP-PrivateLine |
Responsegroup |
Config |
Wer eine IVR-Lösung auf Basis des Lync Response Group Service bereitstellt, muss diesen Workflows auch eine Rufnummer geben. |
Callpark |
Config |
Auch die "Call Park-Parkschleifen" für das temporäre Parken von Anrufern belegen Nummern. |
Exchange AA |
Domain |
Wer Exchange UM einsetzt, der wird mit Lync auch die Objekte für den AutoAttendant anlegen, um Anrufer eine einfache IVR-Anwendung zu eröffnen. |
Exchange SA |
Domain |
Der Exchange Subscriber Access ist die Nummer, unter der Anwender selbst auf ihr Postfach per Telefon zugreifen können. |
Conference Dialin |
Config |
Für die Einwahl in Lync Konferenzen muss mindestens eine Nummer vorgehalten werden. |
AnalogPhone |
Domain |
Die seit Lync möglichen "Analoge Telefone", die an Gateways angebunden sind, werden ebenfalls in Lync definiert |
CommonAreaPhone |
Domain |
Der zweite neue Telefonapparatetyp ist das DCommon Area Phone |
Audio Test Service |
Configuration |
Normalerweise hat der Audio Test Service keine Rufnummer. Wer aber z.B. sein Gateway "testen" möchte, kann dies auch aus dem Telefonnetz tun. |
Unassigned Numer |
Configuration |
Wenn keine der vorgenannten Nummern "matched", dann gibt es immer noch die "unassignedNumner"-Konfiguration, mit der Rufnummernbereiche bedient werden können, z.B. mit einer Ansage oder als Weiterleitung auf eine andere Nummer. |
Sie sehen also eine ganze Menge von möglichen Endpunkten. Und ich bin nicht mal sicher, ob ich damit alle habe.
Abfrage
Auch wenn in Lync eigentlich "fast" alle Objekte per PowerShell abzufragen sind, habe ich mich doch für eine einfache AD-Abfrage ohne Lync Module entschieden, da damit die Auswertung auf jeden PC und mit jedem Benutzer ausgeführt werden kann, der den globalen Katalog lesen darf. für eine Suche nutze ich einfach folgenden LDAP-String:
(|(msRTCSIP-Line=*)(msRTCSIP-PrivateLine=*))
Diesen Filter können Sie z.B. mit CSVDE oder LDIF direkt verwenden:
REM bitte als Server einen GC in ihrer Umgebung verwenden csvde -s gcname:3268 -r "(|(msRTCSIP-Line=*)(msRTCSIP-PrivateLine=*))" -f test.csv -l msRTCSIP-PrivateLine,msRTCSIP-Line
Natürlich muss ich die Ergebnisse dann selbst entsprechend aufbereiten und die einzelnen Felder auswerten, z.B.:
Feldname | Beschreibung | Inhalt |
---|---|---|
msrtcsip-optionflags |
Enthält binäre codiert die Funktionalität |
PConly
0xxx0xx0xxxx |
msrtcsip-ownerurn |
Klassifiziert den Dienst genauer |
CommonAreaPhone urn:device:commonareaphone |
otherIpPhone |
Anhand des Inhalts in diesem Feld lassen sich die Exchange UM-Kontakte erkennen. |
Enthält "opaque=app:exum". Zusätzlich muss noch msrtcsip-optionflags ausgewertet werden. Wenn "-band 1024" zutrifft, dann ist es ein AutoAttendant |
Überprüfung von Feldern
Mit einer stumpfen Ausgabe der Inhalte wäre ich nun schon fast fertig. Aber wenn ich die Daten eh schon habe, dann möchte ich auch ein paar Checks durchführen.
- Rufnummer ohne EV
Wer eine Rufnummer hat, aber nicht für "Enterprise Voice" aktiviert ist, ist wahrscheinlich falsch konfiguriert - Gültige Nummern
Wenn dem Script ein "REGEX-"Ausdruck übergeben wird, der einen korrekten Nummernbereich benennt, dann kann auch dies geprüft werden. Natürlich wäre es sogar noch interessant eine RegularExpress zu definieren, um "gültige" Nummern zu erkennen.
Achtung: Im Skript ist meine "Net at Work-Nummer" als Muster vordefiniert. Übergeben Sie daher ihren Ausdruck per Parameter oder ändern Sie das Skript ab. Vergessen Sie auch nicht das "tel:" davor.
- Dubletten und Extensioncheck
Die Erkennung doppelter Rufnummern ist natürlich naheliegend. Wobei das nicht ohne einen Extensioncheck erfolgen kann. Eine Rufnummer kann ja ohne Extension als "Tel:+495251304600" geschrieben werden, Wer aber auch Lync Phones per Extension anmelden will, wird eher "Tel:+495251304600;ext=600" schreiben, so dass die Extension den letzten Stellen der Rufnummer entspricht. Es gibt aber auch Länder wie die USA, bei denen alle die gleiche "Stammnummer" haben und sich die Extension unterscheidet. Die muss dann aber auch eindeutig sein.
Weitere Überprüfungen sind natürlich denkbar. Ich hatte anfangs z.B. auch eine Prüfung auf die Eindeutigkeit der SIP-Adresse eingebaut. da ich aber nur nach Objekten mit "Rufnummern" suche, wäre das Ergebnis nicht komplett.
Ausgabe
Am einfachsten ist die Ausgabe als CSV-Datei, da diese sehr schnell in Excel oder anderen Werkzeugen weiter verarbeitet werden kann und selbst ein SORT und WHERE ist mit PowerShell trivial. Die Ausgabe erfolgt demnach auf die Pipeline und kann von ihnen per "Export-CSV" weiter gegeben werden. Die die Ausgabe mit GM. damit sie die einzelnen Felder shene
PS C:\> .\get-csphonenumber.ps1 | gm loading Lync Recipients Total objects found: xx writing AD-Search Result to XML write Lync Recipients to CSV TypeName: System.Management.Automation.PSCustomObject Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() adspath NoteProperty System.String adspath=GC://netatwork.de/CN=Carius\, Frank,OU=Technik,OU=Abteilung,DC=netatwork,DC=de AudioVideo NoteProperty System.String AudioVideo=EV Displayname NoteProperty System.String Displayname=Carius, Frank Extension NoteProperty System.String Extension=613 Federation NoteProperty System.Boolean Federation=True Name NoteProperty System.String Name=Carius, Frank RCCUri NoteProperty System.String RCCUri=sip:613@csta.netatwork.de Resforst NoteProperty System.Boolean Resforst=False RTCenabled NoteProperty System.DirectoryServices.ResultPropertyValueCollection RTCenabled=System.DirectoryServices.ResultPro... SIPUri NoteProperty System.String SIPUri=sip:frank.carius@netatwork.de Status NoteProperty System.String Status=OK Statusdetail NoteProperty System.String Statusdetail=OK TELUri NoteProperty System.String TELUri=tel:+495251304613;ext=613 Type NoteProperty System.String Type=User Public
Für eventuelle Fehler werden die Ergebnisse der AD-Suche und der Liste in XML/CSV-Dateien exportiert. Die beiden Zeilen müssen Sie auskommen tieren, wenn Sie dies nicht möchten.
$colresults | export-clixml
'.\adsearchresult.xml'
$list | export-csv .\numbers.csv
Die Dateien helfen mir aber bei einer etwaigen Fehlersuche oder wenn Ergebnisse nicht
PS C:\>
.\get-csphonenumber.ps1 | `
Export-Csv .\lyncphone.20120408.csv -Delimiter ";" -notypeinformation
Ebenso können Sie die Daten dann natürlich auch filtern.
Download
Für die Ausführung des Skripts benötigen Sie einzige eine PowerShell auf ihrem PC und "Lese-Rechte" im Active Directory. Genau genommen erfüllen diese Voraussetzungen alle Domänen Benutzer auf einem halbwegs aktuellen Betriebssystem.
Daher werde ich das Skript nicht öffentlich zur Verfügung stellen, um es nicht allzu einfach zu machen, eine Liste der Rufnummern und Berechtigungen zu erstellen.
Das Skript ist aktuell noch nicht öffentlich. Da ich die Daten aus den LDAP-Feldern anstatt per Lync PowerShell auslese, möchte ich erst einige Daten aus produktiven Umgebungen haben, um die Ergebnisse zu bestätigen.
Ausgehend von dem Feedback dieser Personen werde ich überlegen, wie ich das Skript sinnvoll verfügbar machen kann.
Weiterentwicklung
Wenn man eh schon filtern kann, dann könnte das Skript zukünftig ja auch alle SIP-aktivierten Konten heranholen und als Liste ausgeben. Dann wären auch noch umfangreichere Prüfungen möglich.
Weitere Links
- OCS Felder
- PowerShell Beispiele
- ADSI und LDAP
- Lync Audit Tool
http://www.appvnet.com/services-view/lyncaudittool/ - Lync numbers in use
http://gallery.technet.microsoft.com/office/Lync-numbers-in-use-6c890b9a - SCRIPT:
List-UnusedNumbers.ps1
http://msunified.net/lyncdownloads/script-list-unusednumbers-ps1/ - Updated Get-SkypefBNumbers.ps1
http://lyncnumbers.net/2015/10/20/updated-get-SkypefBnumbers-ps1/
https://gallery.technet.microsoft.com/lync/Get-Skype-for-Business-f2af9408 - Find next available number
(DID) and extension and assign
it to Users or devices
http://gallery.technet.microsoft.com/Find-next-available-number-58391c72