none
Höchste HomePhone Nummer ermitteln und diese um 1 erhöhen RRS feed

  • Frage

  • Hallo zusammen,

    wir haben in unserem AD den Eintrag "Privat" (alias HomePhone) für eine Schnittstelle zu unserem Ticketsystem als eindeutige Benutzer-ID missbraucht. Aktuell sitze ich an einem PowerShell-Script zur einfacheren und fehlerfreieren Anlage von Benutzern. Leider bin ich gerade eben auf ein Problem gestoßen, welches sich für mich als unlösbar darstellt - wohl weil mir die Erfahrung fehlt, aber ich weiß es nicht.

    Mit

    $ADUsers = Get-ADUser -Filter * -SearchBase "OU=$OU2,OU=$OU1,DC=$DC2,DC=$DC1" -Properties * | Select-Object HomePhone

    lade ich uns alle HomePhone-Einträge in das Array $ADUsers - soweit so gut. Ich kann mir die Einträge auch anzeigen lassen (Da es in meiner Test-OU nur 4 gibt, ist das auch relativ schnell, einfach und fehlerfrei geschehen. Angezeigt werden mir dann als Ergebnis

    HomePhone
    ---------
    
    1000384
    1000385
    9000001

    Problem Nummer 1: Die erste Zeile mit dem "Nullwert" stört. Solange man nur einen Nullwert hat, springt man im Array halt einfach die Zeile 1 an, statt der Zeile 0. Keine Lösung aber fürs Erste ein Workaround - wenn es für Problem 2 eine Lösung gibt, wird die sicher auch helfen Problem 1 zu eliminieren.

    Problem Nummer 2: Mit keiner ergoogelten Lösung ist es mir gelungen, diese Einträge als Zahlen verglichen und dementsprechend automatisch den nächst höheren Wert ermittelt zu bekomme.

    Ich habe es mit einer Hashtabelle versucht, bin allerdings am Datentyp gescheitert. Ich habe es mit measure -maximum probiert, bin aber auch da wieder am Datentyp gescheitert. Das Problem stellt sich für mich so dar, dass die Werte eigentlich als @{HomePhone=9000001} im Array stehen, es diese aber nicht in jedem Context so ausgibt. Stringmanipulationen sind natürlich auch gescheitert. Ich bin an der Stelle ratlos. Ich möchte doch im Grunde nur, dass mir das Script für den nächsten, neuen Benutzer automatisch die 9000002 als nächst höhere Nummer auswählt. Ist diese dann vorhanden, eben beim nächsten Mal die 9000003 usw.

    Wäre nett, wenn mir bei dem Problem jemand helfen kann - ich sitze jetzt hier fast 2 Stunden und verzweifel daran, insbesondere, da der Rest des Scripts inzwischen eigentlich steht (inklusive GUI für Gruppenrechtevergabe). Es wäre sehr ärgerlich, wenn es an so einer Banalität (meiner Meinung nach) wie der ID unseres Ticketsystems pro Benutzer scheitern würde.

    Grüße

    Herberttito

    Edit:

    Mal zur Sicherheit noch den Rest vom Script - dann braucht hier keiner der eventuell ebenfalls das Problem analysieren will, alles selbst schreiben:

    import-module ActiveDirectory
    
    $DC1 = "local" #oder Äquivalent
    $DC2 = DOMÄNENNAME #der AD-Name ohne .local oder Äquivalent - dieses gehört unter DC1
    $OU1 = "" #OU der Benutzer direkt unter der Domäne
    $OU2 = "" #eventuelle Unter-OU erste Ebene
    $OU3 = "" #eventuelle Unter-OU zweite Ebene (tiefer geht es bei uns nicht=
    
    #Deklaration des Arrays
    $ADUsers = @()
    
    $ADUsers = Get-ADUser -Filter * -SearchBase "OU=$OU2,OU=$OU1,DC=$DC2,DC=$DC1" -Properties * | Select-Object HomePhone
    $ADUsersCounter = @($ADUsers).Count
    
    $ADUsersCounter
    $ADUsers
    
    Write-Host "Beliebige Taste zum beenden drücken ..."
    $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")


    Montag, 19. August 2013 16:34

Antworten

  • Brima hat das Property length genommen (warum auch immer) du möchtest aber das Property HomePhone haben. Nimm bitte 1 zu 1 meinen code den ich von angepasst habe!

    [int[]]$ADUsers = Get-ADUser -Filter * -SearchBase "OU=$OU2,OU=$OU1,DC=$DC2,DC=$DC1" -Properties HomePhone | Select-Object -ExpandProperty HomePhone -ErrorAction silentlycontinue | ForEach-Object {[int]($_.tostring())} | Sort-Object
    $NaechsterWert = ++$ADUsers[-1]


    Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
    Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
    My PowerShell Blog http://www.admin-source.info
    [string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
    German ? Come to German PowerShell Forum!




    Dienstag, 20. August 2013 08:19
  • $_ Underline enthaelt immer den aktuellen Wert!

    0..9 | foreach-object {"Ziffern: {0}" -f $_}

    Der Code gibt nacheinander die Ziffern 0-9 in die  Pipe und fuer jede Ziffer wird dann der Text ausggeben, d.h. wenn die 0 uebergeben wird hat $_ den Wert0, dann die 1 und so weiter.

    Ab der Powershell 3.0 kannst Du anstelle von $_ auch $PSItem verwenden.

    0..9 | foreach-object {"Ziffern: {0}" -f $PSItem}

    Die beiden Klammern () haben nichts mit einem Array zu tun, sondern enthalten die Argumente fuer die Methode tostring, in unserem Fall uebergeben wir keine Argumente, deshalb ist das Klammerpaar leer, die Methode tostring ist eine ueberladene Methode, d.h. man kann sie mit diversen Argumentenkombinationen aufrufen.  Wie die aussehen verraet die Powershell ueber den Befehl Get-Member, also z.B:  

    $a = 5
    $a | Get-Member


    dort findest Du dann auch folgende Zeile

    ToString    Method     string ToString(), string ToString(string format), string ToString(System.IFormatProvider pro...

    Und wie du siehst haben wir die erste Ueberladung genutzt.

    Beste Gruese
    brima






    Dienstag, 20. August 2013 12:43

Alle Antworten

  • Hallo,

    ich habe hier zu Hause leider kein AD und bin zu faul mich in der Firma einzuloggen, aber probiere mal das hier.

    [int[]]$ADUsers = Get-ADUser -Filter * -Properties HomePhone -SearchBase "OU=$OU2,OU=$OU1,DC=$DC2,DC=$DC1" | Select-Object -ExpandProperty HomePhone -ErrorAction silentlycontinue | ForEach-Object {$_.tostring()} | Sort-Object

    Den groessten Wert kannst Du dann mit dem Index -1 ansprechen.

    $ADUsers[-1]

    $NaechsterWert = ++$ADUsers[-1]

    Aber ich wuerde den naechsten Wert nur einmal auf diese Art ermitteln, und ihn dann in einer Datei, Registry oder abzulegen und Ihn dann dort auszulesen und aktualisiert wieder zu speichern, denn es ist nicht produktiv jedesmal das AD nach dem Wert zu durchsuchen.

    Beste Gruesse
    brima

    - Property korrigiert



    • Bearbeitet brima Dienstag, 20. August 2013 09:31
    Montag, 19. August 2013 19:24
  • Hallo Herberttito

    Eure Vorgehensweise ist aus folgenden Gründen Unsinnig:

    1. Jedes mal alle User einzulesen belastet die Active Directory Server, dies sollte vermieden werden

    2. Eine Zahl die eine eindeutige Nummer darstellen soll, sollte und kann es nur einmal geben!
    Was ist wenn mehrere User in Rente gehen oder entlassen werden und dann aus dem Active Directory gelöscht werden? Dann fällt euer Kartenhaus zusammen!

    Das Aktive Directory dazu zu missbrauchen ist keine gute Idee!
    Am besten ist natürlich eine Datenbank dafür geeignet!
    Wenn das nicht geht nehmt eine Datei auf einem Share wo die Nummer hochgezählt wird!(Vorsicht File lock!")
    Wenn das nicht geht missbraucht  eine Active Directory Gruppe die nur diesem Zweck dient! Dort könnt ihr in das Feld Description (Semikolon separierte) Daten reinschreiben.

    Die Lösung von Brima ist gut!

    [int[]]$ADUsers = Get-ADUser -Filter * -SearchBase "OU=$OU2,OU=$OU1,DC=$DC2,DC=$DC1" -Properties HomePhone| Select-Object -ExpandProperty SID -ErrorAction silentlycontinue | ForEach-Object {$_.tostring()} | Sort-Object

    $NaechsterWert = ++$ADUsers[-1]



    Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
    Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
    My PowerShell Blog http://www.admin-source.info
    [string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
    German ? Come to German PowerShell Forum!


    Dienstag, 20. August 2013 06:39
  • Hallo ihr beiden,

    vielen Dank für die Infos und den Lösungsvorschlag.

    Das diese Lösung nicht schön ist, ist mir durchaus bewusst. Leider habe ich darauf keinen Einfluss, da es nicht in meinen Verantwortungsbereich fällt. Unser AD ist jedoch nicht so riesig, als das sich einer der drei AD-Controller über zuviel Last beklagen könnte. Unsere Umgebung umfasst ca. 250 aktive Benutzer - ausgeschiedene werden nicht gelöscht, sondern deaktiviert und bleiben unbegrenzt bestehen.

    Neue Benutzer kommen bei uns eventuell 5 pro Monat dazu. Um die Abfragen und Last zu reduzieren, wird auch explizit nur eine bestimmte OU und deren Benutzer ausgelesen (unsere Benutzer verteilen sich auf mehrere OUs). Ob dies automatisch per Powershell geschieht, oder händisch über die Suche im AD macht meines Wissens nach keinen Unterschied.

    Den Ansatz diese Zahl in eine Gruppe oder eine Datei zu schreiben verstehe ich und würde ich auch gerne umsetzen, leider ist das aber nicht möglich, da das Kartenhaus dann auch wieder zusammenbricht, sowie einer einen Benutzer händisch anlegt oder händisch eine ID vergibt.

    Der von Birma gepostete Code übersteigt meine Fähigkeiten - was bewirkt denn das [int[]] vor der Variablen?

    [int[]]$ADUsers = Get-ADUser -Filter * -SearchBase "OU=$OU2,OU=$OU1,DC=$DC2,DC=$DC1" | Select-Object -ExpandProperty length -ErrorAction silentlycontinue | ForEach-Object {$_.tostring()} | Sort-Object

    Ich habe es mir jetzt mal einfach gemacht und den Code 1 zu 1 übernommen. Er führt jedoch zu der Fehlermeldung "In einem NULL-Array kann kein Index erstellt werden. + CategoryInfo: InvalidOperation: (-1:Int32) [], RuntimeException.

    Grüße

    Herberttito

    Dienstag, 20. August 2013 07:57
  • Hallo,

    also [int] alleine definiert das die Variable ein Integer ist, und [int[]] definiert wiederum, das es sich um ein Array mit Integer Werten hnadelt.

    Beste Gruesse
    brima 

    Dienstag, 20. August 2013 08:08
  • Brima hat das Property length genommen (warum auch immer) du möchtest aber das Property HomePhone haben. Nimm bitte 1 zu 1 meinen code den ich von angepasst habe!

    [int[]]$ADUsers = Get-ADUser -Filter * -SearchBase "OU=$OU2,OU=$OU1,DC=$DC2,DC=$DC1" -Properties HomePhone | Select-Object -ExpandProperty HomePhone -ErrorAction silentlycontinue | ForEach-Object {[int]($_.tostring())} | Sort-Object
    $NaechsterWert = ++$ADUsers[-1]


    Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
    Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
    My PowerShell Blog http://www.admin-source.info
    [string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
    German ? Come to German PowerShell Forum!




    Dienstag, 20. August 2013 08:19
  • Hallo,

    danke Peter, das ist rictig, ich hatte ein wenig mit Get-childitem getestet, wei es dieses Property bei folders nicht gefeullt ist, um den Effekt zu bekommen, Property befuellt oder nicht, mir ist die Nacht im Bett eingefallen das ich es nicht angeappst hatte in meinem Post.

    Ich woltle es heute morgen hier im AD nochmal testen und den Post aendern aber Du warst schneller. :-)

    Danke Dir.

    Beste Gruesse
    brima

    Dienstag, 20. August 2013 09:27
  • Sorry ihr beiden, da hätte ich aber eigentlich ja auch drauf kommen können. Ich konnte nur mit ExpandProperty nichts anfangen und Length dahinter hatte mich dann völlig aus dem Konzept gebracht. Hatte in dem Moment das Büro voll und eine lebhafte Diskussion ohne meine Beteiligung hier - da merke ich wieder, dass ich Ruhe brauche, wenn ich Scripten soll. Nichts desto trotz hätte ich die Lösung ohne eure Hilfe nicht gefunden!

    Wie auch immer, die Lösung funktioniert - vielen Dank. Meine Euphorie wird nur gebremst, weil Peter mit seinen Aussagen völlig Recht hat hinsichtlich Belastung AD. Nicht das wir davon etwas merken würden, aber mir ist bei solchen Lösungen die Daten vom AD immer wieder abrufen, nicht ganz wohl.

    Eine Frage ist jedoch für mich noch offen geblieben. Was bewirkt

    ForEach-Object {[int]($_.tostring())}

    Ich würde darunter verstehen, dass dabei jeder Wert in einen String umgewandelt wird, richtig? Wofür steht aber dann der Unterstrich hinter der Variablendeklaration? Der Punkt verkettet meines Wissens nach und die Klammern wurden gewählt, weil es sich um ein Array handelt?

    Grüße

    Herberttito



    • Bearbeitet Herberttito Dienstag, 20. August 2013 12:34
    Dienstag, 20. August 2013 12:31
  • $_ Underline enthaelt immer den aktuellen Wert!

    0..9 | foreach-object {"Ziffern: {0}" -f $_}

    Der Code gibt nacheinander die Ziffern 0-9 in die  Pipe und fuer jede Ziffer wird dann der Text ausggeben, d.h. wenn die 0 uebergeben wird hat $_ den Wert0, dann die 1 und so weiter.

    Ab der Powershell 3.0 kannst Du anstelle von $_ auch $PSItem verwenden.

    0..9 | foreach-object {"Ziffern: {0}" -f $PSItem}

    Die beiden Klammern () haben nichts mit einem Array zu tun, sondern enthalten die Argumente fuer die Methode tostring, in unserem Fall uebergeben wir keine Argumente, deshalb ist das Klammerpaar leer, die Methode tostring ist eine ueberladene Methode, d.h. man kann sie mit diversen Argumentenkombinationen aufrufen.  Wie die aussehen verraet die Powershell ueber den Befehl Get-Member, also z.B:  

    $a = 5
    $a | Get-Member


    dort findest Du dann auch folgende Zeile

    ToString    Method     string ToString(), string ToString(string format), string ToString(System.IFormatProvider pro...

    Und wie du siehst haben wir die erste Ueberladung genutzt.

    Beste Gruese
    brima






    Dienstag, 20. August 2013 12:43
  • Herbettito, ist das Problem gelöst? Dann markiere bitte die richtige(n) Antwort(en).

    Danke!


    Blog: http://bytecookie.wordpress.com
    Powershell Codesnippet Manager: Link

    Hilf mit und markiere hilfreiche Beiträge mit dem "Abstimmen"-Button (links) und Beiträge die eine Frage von dir beantwortet haben, als "Antwort" (unten).
    Warum das Ganze? Hier gibts die Antwort.

    Donnerstag, 22. August 2013 17:17
    Moderator