Telefonnummern im Active Directory per Powershell formatieren bzw. vereinheitlichen
Hallo,
ich habe den Auftrag bekommen die Formatierung sämtlicher Telefon/Faxnummern aller Benutzer in unserer Windows 2008 R2 Domäne zu ändern, damit diese aus der Active Directory entsprechend in den Signaturen gezogen werden.
Ich dachte mir, dass ich einen String nehme und diesen durch die neue Formatierung ersetze.
Alter String: +49 (0)123-456789-
Neuer String: +49 123 456789-
Hinter den Strings ist noch jeweils eine 4 stellige Durchwahl.
Exchange 2010 SP1 und damit die entsprechenden Powershell Befehle "get-user" und "set-user" sind vorhanden!
Wie kann ich hier mittels Powershell am besten vorgehen?
Viele Grüße
Stefan
ich habe den Auftrag bekommen die Formatierung sämtlicher Telefon/Faxnummern aller Benutzer in unserer Windows 2008 R2 Domäne zu ändern, damit diese aus der Active Directory entsprechend in den Signaturen gezogen werden.
Ich dachte mir, dass ich einen String nehme und diesen durch die neue Formatierung ersetze.
Alter String: +49 (0)123-456789-
Neuer String: +49 123 456789-
Hinter den Strings ist noch jeweils eine 4 stellige Durchwahl.
Exchange 2010 SP1 und damit die entsprechenden Powershell Befehle "get-user" und "set-user" sind vorhanden!
Wie kann ich hier mittels Powershell am besten vorgehen?
Viele Grüße
Stefan
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 180245
Url: https://administrator.de/contentid/180245
Ausgedruckt am: 24.11.2024 um 04:11 Uhr
32 Kommentare
Neuester Kommentar
Servus @blackhawk17 / @StefanK007 ,
auch wenn der Beitrag schon ein paar Jahre auf dem Buckel hat, poste ich hier mal eine umfassende Lösung da hier immer wieder die Anfrage zum Thema kommt.
Ich mache das immer mit meinem folgendem Script. Es erkennt den Ländercode sowie deutsche Vorwahlen (inkl. Handynetze) automatisch (selbst wenn keine Trennzeichen dazwischen verwendet wurden!) und formatiert die Nummern per Default im DIN-Format
Das Format lässt sich aber per CMDLet-Parameter (-format) und Platzhaltern nach eigenen Bedürfnissen anpassen.
Sonderzeichen außer Nummern und + werden aus den Nummern entfernt.
Den Default-Country-Code welcher eingesetzt wird wenn eine Nummer keinen Ländercode beinhaltet kannst du im Skript in Zeile 5 angeben.
Ebenfalls lässt sich im Array $attributes die Liste der LDAP Attribute festlegen welche das Skript untersuchen und ändern soll.
Den Download des Skriptes gibt es hier:
Viel Spaß beim Anwenden
Grüße Uwe
auch wenn der Beitrag schon ein paar Jahre auf dem Buckel hat, poste ich hier mal eine umfassende Lösung da hier immer wieder die Anfrage zum Thema kommt.
Ich mache das immer mit meinem folgendem Script. Es erkennt den Ländercode sowie deutsche Vorwahlen (inkl. Handynetze) automatisch (selbst wenn keine Trennzeichen dazwischen verwendet wurden!) und formatiert die Nummern per Default im DIN-Format
+[COUNTRYCODE] [AREACODE [SUBSCRIBER]-[EXTENSION]
Sonderzeichen außer Nummern und + werden aus den Nummern entfernt.
Den Default-Country-Code welcher eingesetzt wird wenn eine Nummer keinen Ländercode beinhaltet kannst du im Skript in Zeile 5 angeben.
Ebenfalls lässt sich im Array $attributes die Liste der LDAP Attribute festlegen welche das Skript untersuchen und ändern soll.
Den Download des Skriptes gibt es hier:
format_phone_numbers_180245.zip
Viel Spaß beim Anwenden
Grüße Uwe
Zitat von @blackhawk17:
Sag mal, wenn ich die Klammern () in der Vorwahl behalten möchte, wäre das nen riesen Aufwand die ins Skript wieder rein zu nehmen?
Nein, kein Problem, ändere Zeile 52 so abSag mal, wenn ich die Klammern () in der Vorwahl behalten möchte, wäre das nen riesen Aufwand die ins Skript wieder rein zu nehmen?
$acode = "(" + $acode.Substring(0,$_) + ")"
Sorry ich muss nochmal was fragen
Nach der Vorwahl bei Festnetztelefonen kommt ja meistens die Anschlussnummer z.B: 123 und dann die Durchwahl 456
z.B. +49 (4888) 123456 so wäre es jetzt, man sieht die Durchwahl nicht mehr.
z.B. +49 (4888) 123-456 das aber allgemein zu programmieren halte ich für schwierig, da einige ja vielleicht auch mehr als 3 Zahlen haben werden.
Könnte man nicht sagen "alles was nach der Ortsvorwahl kommt" bleibt so stehen? Dann hätte man die Durchwahl auch immer schön mit drin?
Wäre das in deinem Skript $rest oder machst du das über den regex Schlüssel? Das erschließt sich mir noch nicht ob ich das evtl. schnell selbst anpassen kann.
vg
Nach der Vorwahl bei Festnetztelefonen kommt ja meistens die Anschlussnummer z.B: 123 und dann die Durchwahl 456
z.B. +49 (4888) 123456 so wäre es jetzt, man sieht die Durchwahl nicht mehr.
z.B. +49 (4888) 123-456 das aber allgemein zu programmieren halte ich für schwierig, da einige ja vielleicht auch mehr als 3 Zahlen haben werden.
Könnte man nicht sagen "alles was nach der Ortsvorwahl kommt" bleibt so stehen? Dann hätte man die Durchwahl auch immer schön mit drin?
Wäre das in deinem Skript $rest oder machst du das über den regex Schlüssel? Das erschließt sich mir noch nicht ob ich das evtl. schnell selbst anpassen kann.
vg
Zitat von @pixel0815:
Das wäre genial. Vielleicht eine Varible für die Anzahl der Nummern für die Durchwahl. Drei oder vierstellung :o)
Das wäre genial. Vielleicht eine Varible für die Anzahl der Nummern für die Durchwahl. Drei oder vierstellung :o)
Hatte ich ihm schon per PN geschickt
#Edit# Skript beinhaltet jetzt per Default auch Extensions, der untere Schnippel ist daher nicht mehr gültig
# extension
if(($number.trim() -match '\b(\d+)$')){
if ($rest.length -gt 0){
$rest = $rest.SubString(0,$rest.length - $matches[1].length) + $matches
}else{
$acode = $acode.SubString(0,$acode.length - $matches[1].length) + $matches
}
}
Grüße Uwe
Habe irgendwie was komisches.
Das Skript läuft los, macht auch ne ganze Reihe an Korrekturen und dann bricht es mit einmal ab.
Folgende Meldung:
get-aduser : Vom Server wurde der folgende Fehler zurückgegeben: Ungültiger Aufzählungskontext.
In Zeile:70 Zeichen:1
+ FullyQualifiedErrorId : Vom Server wurde der folgende Fehler zurückgegeben: Ungültiger Aufzählungskontext.,Microsoft.ActiveDirectory.Management.Commands.GetADUser
War das nun zu viel für ihn? Kann die Meldung irgendwie nicht deuten.
Hast du nochmal einen Tipp für mich?
vg
Das Skript läuft los, macht auch ne ganze Reihe an Korrekturen und dann bricht es mit einmal ab.
Folgende Meldung:
get-aduser : Vom Server wurde der folgende Fehler zurückgegeben: Ungültiger Aufzählungskontext.
In Zeile:70 Zeichen:1
get-aduser -Filter * -ResultSetSize $null -Properties $attributes -PipelineVaria ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: ( [Get-ADUser], ADException+ FullyQualifiedErrorId : Vom Server wurde der folgende Fehler zurückgegeben: Ungültiger Aufzählungskontext.,Microsoft.ActiveDirectory.Management.Commands.GetADUser
War das nun zu viel für ihn? Kann die Meldung irgendwie nicht deuten.
Hast du nochmal einen Tipp für mich?
vg
Machst du das Remote per RSAT und hast mehrere tausend User? Dann schlägt hier vermutlich das Throttling zu und du solltest die -ResultPageSize Property bei Get-ADUser aktiv nutzen, oder pro OU in kleineren Steps durchlaufen.
Mehr dazu steht hier:
https://social.technet.microsoft.com/wiki/contents/articles/32418.active ...
Mehr dazu steht hier:
https://social.technet.microsoft.com/wiki/contents/articles/32418.active ...
Nein, die Seite oben solltest du mal aufmerksamer lesen. In deinem Fall braucht er einfach zu lange für die Pipeline was dann zu einem Timeout führt.
Also speichere die AD-User am einfachsten vorher in einer Variablen dann führt das zu keinem Timeout weil er alle Objekte schon im Voraus geladen hat.
Also speichere die AD-User am einfachsten vorher in einer Variablen dann führt das zu keinem Timeout weil er alle Objekte schon im Voraus geladen hat.
Retrieve your Active Directory objects to a variable first, then send it down the pipeline using the variable. This method is easy to implement in your code without lots of configuration changes in your Active Directory environment. It works because writing the objects to a variable is very fast so your Get-ADUser and Get-ADComputer cmdlets can quickly write all object to the variable and request the next page until all object are received.
$users = get-aduser -Filter * -ResultSetSize $null -Properties $attributes
$users | ?{$user = $_;($attributes | ?{$user.$_ -match '\d+'})} | %{
$user = $_
# ......
# .......
Hallo,
kann ich es nicht auch so machen ? :
Das hat einmal geklappt für eine OU bei der nächsten sagt er mir jetzt:
kann ich es nicht auch so machen ? :
get-aduser -Filter * -SearchBase "Firma 123,OU=Benutzer,DC=contoso,DC=com" -ResultSetSize $null -Properties $attributes -PipelineVariable user | ?{($attributes | ?{$user.$_ -match '\d+'})} | %{
Das hat einmal geklappt für eine OU bei der nächsten sagt er mir jetzt:
get-aduser : The object name has bad syntax
At C:\Telefon.ps1:70 char:1
+ get-aduser -Filter * -SearchBase "XXX GmbH,OU=Corporate Group,DC=XXX, ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-ADUser], ADException
+ FullyQualifiedErrorId : ActiveDirectoryServer:8335,Microsoft.ActiveDirectory.Management.Commands.GetADUser
-SearchBase "Firma 123
Das ist kein valider DN! Dir fehlt das "OU=" davor. Sagt dir auch die Fehlermeldung schon ==>The object name has bad syntax
Muss ich wieder Kaffeeersatz spielen ?!http://www.selfadsi.de/ldap-path.htm
Hallo Ihr lieben Leute, ich bin der Neue :D
ich verwalte zusammen mit einem Kollegen eine AD mit ca. 400 Leuten.
Nun habe auch ich genau die Aufgabe bekommen. Die Telefonnummern sollen formatiert werden.
Sie liegen in allen möglichen Eingabevarianten vor.
Soweit ich das hier überblicke ist das Script hier die Antwort auf meine Frage.
Bislang hatte ich bei Verwalten von kleinen Netzen keinen Anlass die PowerShell zu nutzen und dementsprechend keine tiefen Power-Shell Vorkenntnisse.
Mich interessiert zu dem Script - Beispiel hier, wie ich sicherstellen kann, daß das Script auf eine bestimmte OU angewendet wird. (z.B.) um aus Vorsichtsgründen in einer Test-OU zu proben.
Ich erhoffe mir nicht mühseelig die 400 Accounts bearbeiten zu müssen , dafür ist die Powershell ja da.
herzlichste Grüße
ich verwalte zusammen mit einem Kollegen eine AD mit ca. 400 Leuten.
Nun habe auch ich genau die Aufgabe bekommen. Die Telefonnummern sollen formatiert werden.
Sie liegen in allen möglichen Eingabevarianten vor.
Soweit ich das hier überblicke ist das Script hier die Antwort auf meine Frage.
Bislang hatte ich bei Verwalten von kleinen Netzen keinen Anlass die PowerShell zu nutzen und dementsprechend keine tiefen Power-Shell Vorkenntnisse.
Mich interessiert zu dem Script - Beispiel hier, wie ich sicherstellen kann, daß das Script auf eine bestimmte OU angewendet wird. (z.B.) um aus Vorsichtsgründen in einer Test-OU zu proben.
Ich erhoffe mir nicht mühseelig die 400 Accounts bearbeiten zu müssen , dafür ist die Powershell ja da.
herzlichste Grüße
Servus @aehrfoordt, willkommen auf Administrator.de!
Der Rest in der Zeile bleibt natürlich gleich.
Damit du auch was dazu lernst :Get-AdUser
Grüße Uwe
Powershell Leitfaden für Anfänger
Mich interessiert zu dem Script - Beispiel hier, wie ich sicherstellen kann, daß das Script auf eine bestimmte OU angewendet wird. (z.B.) um aus Vorsichtsgründen in einer Test-OU zu proben.
Zeile 66 einfach den DN der OU mittels -SearchBase Parameter angebenget-aduser -Filter * -ResultSetSize $null -Properties $attributes -SearchBase 'OU=Verwaltung,DC=mydomain,DC=de' -PipelineVariable user
Damit du auch was dazu lernst :Get-AdUser
Grüße Uwe
Powershell Leitfaden für Anfänger
Rückmeldung:
Erster Versuch in einer Test - OU auf meinem Trainings - DC Erfolg
Anwendung auf die gesamte Trainings - AD - Erfolg
Zweiter Versuch in der Produktiv - AD Test - OU - Erfolg
Anwendung auf die Gesamte AD - Erfolg
Das hat mir das Editieren von ca 2000 Einträgen erspart und laut Ausgabe ist nirgendwo eine falsche Nummer herausgekommen.
Herzlichsten Dank nochmal
Erster Versuch in einer Test - OU auf meinem Trainings - DC Erfolg
Anwendung auf die gesamte Trainings - AD - Erfolg
Zweiter Versuch in der Produktiv - AD Test - OU - Erfolg
Anwendung auf die Gesamte AD - Erfolg
Das hat mir das Editieren von ca 2000 Einträgen erspart und laut Ausgabe ist nirgendwo eine falsche Nummer herausgekommen.
Herzlichsten Dank nochmal
Welche Regex muss ich da anpassen wenn ich möchte das die Durchwahl erkennbar ist?
Ich krieg es einfach nicht hin.
Ich krieg es einfach nicht hin.
# extension
if(($number.trim() -match '\-(\d+)$')){
if ($rest.length -gt 1){
$rest = $rest.SubString(0,$rest.length - $matches[1].length) + $matches
}else{
$acode = $acode.SubString(0,$acode.length - $matches[1].length) + $matches
}
}
# return formatted number
return "+$ccode $acode $rest".trim()
Das aktualisierte Skript (17.02.2023) beinhaltet nun auch Extension-Abgrenzung und das Format ist jetzt der Einfachheit halber über die Platzhalter
und einen Format-String im Parameter -format des CMDLets steuerbar.
Zusätzlich können die minimale und maximale Länge für die Erkennung der Extension über zwei Parameter gesteuert werden, im Default minimal=1 und maximal=4 Digits, eine Abgrenzung der Extension per Leerzeichen/Dash/Slash oder anderen Abgrenzungszeichen muss aber zwingend in der Originalnummer vorhanden sein damit diese als Extension erkannt werden kann!
Des weiteren bietet die Funktion jetzt auch direkten Pipeline-Support für mehrere Nummern auf einen Rutsch.
Grüße Uwe
[[COUNTRYCODE]]
[[AREACODE]]
[[SUBSCRIBER]]
[[EXTENSION]]
Zusätzlich können die minimale und maximale Länge für die Erkennung der Extension über zwei Parameter gesteuert werden, im Default minimal=1 und maximal=4 Digits, eine Abgrenzung der Extension per Leerzeichen/Dash/Slash oder anderen Abgrenzungszeichen muss aber zwingend in der Originalnummer vorhanden sein damit diese als Extension erkannt werden kann!
Des weiteren bietet die Funktion jetzt auch direkten Pipeline-Support für mehrere Nummern auf einen Rutsch.
param(
# number to normalize
[Parameter(mandatory=$true,ValueFromPipeline=$true)][ValidateNotNullOrEmpty()][string[]]$number,
# default country code for numbers without it
[Parameter(mandatory=$false)][string]$DefaultCountryCode = '49',
# number output format, supported placeholders (case sensitive): [[COUNTRYCODE]],[[AREACODE]],[[SUBSCRIBER]],[[EXTENSION]]
[Parameter(mandatory=$false)][string]$format = '+[[COUNTRYCODE]] [[AREACODE]] [[SUBSCRIBER]]-[[EXTENSION]]',
# specify min number of digits for detecting extensions
[Parameter(mandatory=$false)][int]$extension_min_digits = 1,
# specify max number of digits for detecting extensions
[Parameter(mandatory=$false)][int]$extension_max_digits = 4
)
Zitat von @colinardo:
Das aktualisierte Skript (17.02.2023) beinhaltet nun auch Extension-Abgrenzung und das Format ist jetzt der Einfachheit halber über die Platzhalter
und einen Format-String im Parameter -format des CMDLets steuerbar.
Zusätzlich können die minimale und maximale Länge für die Erkennung der Extension über zwei Parameter gesteuert werden, im Default minimal=1 und maximal=4 Digits, eine Abgrenzung der Extension per Leerzeichen/Dash/Slash oder anderen Abgrenzungszeichen muss aber in der Originalnummer vorhanden sein.
Des weiteren bietet die Funktion jetzt auch direkten Pipeline-Support für mehrere Nummern auf einen Rutsch.
Grüße Uwe
Das aktualisierte Skript (17.02.2023) beinhaltet nun auch Extension-Abgrenzung und das Format ist jetzt der Einfachheit halber über die Platzhalter
[[COUNTRYCODE]]
[[AREACODE]]
[[SUBSCRIBER]]
[[EXTENSION]]
Zusätzlich können die minimale und maximale Länge für die Erkennung der Extension über zwei Parameter gesteuert werden, im Default minimal=1 und maximal=4 Digits, eine Abgrenzung der Extension per Leerzeichen/Dash/Slash oder anderen Abgrenzungszeichen muss aber in der Originalnummer vorhanden sein.
Des weiteren bietet die Funktion jetzt auch direkten Pipeline-Support für mehrere Nummern auf einen Rutsch.
param(
# number to normalize
[Parameter(mandatory=$true,ValueFromPipeline=$true)][ValidateNotNullOrEmpty()][string[]]$number,
# default country code for numbers without it
[Parameter(mandatory=$false)][string]$DefaultCountryCode = '49',
# number output format, supported placeholders (case sensitive): [[COUNTRYCODE]],[[AREACODE]],[[SUBSCRIBER]],[[EXTENSION]]
[Parameter(mandatory=$false)][string]$format = '+[[COUNTRYCODE]] [[AREACODE]] [[SUBSCRIBER]]-[[EXTENSION]]',
# specify min number of digits for detecting extensions
[Parameter(mandatory=$false)][int]$extension_min_digits = 1,
# specify max number of digits for detecting extensions
[Parameter(mandatory=$false)][int]$extension_max_digits = 4
)
Hallo Uwe,
ich hab das Skript gekauft und es funktioniert wunderbar - bis auf einige Ausnahmen.
Im AD steht unter der Telefonnummer zum Beispiel 012345 4445000
Lasse ich das Skript laufen, erscheint dann folgendes
Korrigiere Nummern für 'xxxxx' 'xxxxx'
Number Old value New value
------ --------- ---------
telephoneNumber 012345 4445000 +49 12345 4445000
Die 4 Stellige Extension wird nicht erkannt. Toll wäre, wenn man auch die Rumpfrufnummer einstellen kann. Also z.b. 3 Stellig etc. Ist das sinnvoll?
Einstellungen sind wie folgt
# number to normalize
[Parameter(mandatory=$true,ValueFromPipeline=$true)][ValidateNotNullOrEmpty()][string[]]$number,
# default country code for numbers without it
[Parameter(mandatory=$false)][string]$DefaultCountryCode = '49',
# number output format, supported placeholders (case sensitive): [[COUNTRYCODE]],[[AREACODE]],[[SUBSCRIBER]],[[EXTENSION]]
[Parameter(mandatory=$false)][string]$format = '+[[COUNTRYCODE]] [[AREACODE]] [[SUBSCRIBER]]-[[EXTENSION]]',
# specify min number of digits for detecting extensions
[Parameter(mandatory=$false)][int]$extension_min_digits = 1,
# specify max number of digits for detecting extensions
[Parameter(mandatory=$false)][int]$extension_max_digits = 4
Servus.
Ist das bei dir nicht der Fall entferne das \b aus dem Regex dieser Zeile, dann werden Extensions auch angewendet wenn vorher kein Trennzeichen vorhanden war.
Grüße Uwe
Die 4 Stellige Extension wird nicht erkannt.
Du hast scheinbar meinen Hinweis dazu nicht gelesen. Im Wortlaut:Zitat von @colinardo:
Eine Abgrenzung der Extension per Leerzeichen/Dash/Slash oder anderen Abgrenzungszeichen muss aber in der Originalnummer vorhanden sein.
Extensions werden also nur angewendet wenn diese vorher schon vom Rest durch ein Boundary-String (in Regex: \b) abgetrennt waren.Eine Abgrenzung der Extension per Leerzeichen/Dash/Slash oder anderen Abgrenzungszeichen muss aber in der Originalnummer vorhanden sein.
Ist das bei dir nicht der Fall entferne das \b aus dem Regex dieser Zeile, dann werden Extensions auch angewendet wenn vorher kein Trennzeichen vorhanden war.
if ($num.trim() -match "(\b{$extension_min_digits,$extension_max_digits})$"){
Grüße Uwe