Benutzer mit den meisten Antworten
TerminateADUser – Get-ADPrincipalGroupMembership – MemberOf und CSV Export

Frage
-
Hallo Zusammen,
ich möchte mittels einem PS Skript AD Benutzerkonten geregelt terminieren.
Hierzu habe eine PS-Skript Function erstellt, die mit einem Parameter -AccountToTerminate 'SamAccountName' gestartet werden soll.
Innerhalb des Skripts sollen zum AD-Object und seinen Funktionen wichtige Informationen in "eine" CSV-Datei zum entsprechenden Job (Job-ID) ablegt werden.
Einzelne Attributen und Werten stellen kein Problem dar, jedoch stoße ich bei der Verarbeitung von String-Arrays oder Typ "System.Array" immer wieder auf Probleme, was auch an meinem Verständnis liegen mag. :-(
Ich möchte für den ausgewählten Benutzer, eine CSV-Tabelle erstellen, mit Spalten:
DisplayName, SamAccountName, SID, etc.
sowie z.B. eine Spalte für die aktuellen Gruppenmitgliedschaften
MemberOf, MemberOfSID
oder die benutzen ActiveSync Geräte:
MobileDevices, etc.
Folgender Code (nur Teile) nutze ich zum sammeln der Informationen und dem Export ($efile):
CODE:
# Auswahl SamAccountName $AccountToTerminate = 'mustermann.max' # Auslesen AD-Attribute und Funktionen $ADUser = Get-ADUser -Identity $AccountToTerminate -Property * | Sort-Object $UserMemberOf = Get-ADPrincipalGroupMembership -Identity $AccountToTerminate | Select-Object SamAccountName, SID IF ($ADUser.'msExchMailboxGuid' -eq $Null){ [String]$UserMailboxEnabled = "Disabled" [String]$UserEmailAddress = "NotSet" } ELSE { [String]$UserMailboxEnabled = "Enabled" [String]$UserEmailAddress = $ADUser.'mail' $UserMailbox = Get-Mailbox $AccountToTerminate $UserCASMailbox = Get-CASMailbox $AccountToTerminate $UserMobileDevices = Get-MobileDeviceStatistics -Mailbox $AccountToTerminate } # Ergebnisse zusammenbauen [Array]$Result = @() $Object = New-Object PSObject Add-Member -InputObject $Object -memberType NoteProperty -Name DisplayName -Value $ADUser.'DisplayName' Add-Member -InputObject $Object -memberType NoteProperty -Name SamAccountName -Value $ADUser.'SamAccountName' Add-Member -InputObject $Object -memberType NoteProperty -Name SID -Value $ADUser.'objectSID'.Value Add-Member -InputObject $Object -memberType NoteProperty -Name MailboxEnabled -Value $UserMailboxEnabled Add-Member -InputObject $Object -memberType NoteProperty -Name EmailAddress -Value $UserEmailAddress # Add-Member -InputObject $Object -memberType NoteProperty -Name MemberOf -Value $UserMemberOf.SamAccountName Add-Member -InputObject $Object -memberType NoteProperty -Name MemberOfSID -Value $UserMemberOf.SID.Value $Result += $Object # Ergebnisse in eine CSV Datei exportieren und diese öffnen $Result | Export-Csv -Path $efile -Delimiter ";" -Encoding UTF8 -NoTypeInformation -ErrorAction $ErrorActionPreference & $efile
Nun die Frage!
1. Wie bekommt man es hin, die Mehrfach Werte (wie zum Beispiel 'MemberOf' oder 'MemberOfSID' in NUR eine "Spalte 'MemberOfSID'" in das $Result Array zu bringen und auch zu exportieren?
Also zum Benutzer und seine Werte NUR eine Spalte "MemberOf" und darunter alle Gruppenmitgliedschaften?
Jeder Ansatz von mir, mit Schleifen oder 'System.Collections.ArrayList' führten zu keinem Ergbenis.
Der direkte CSV-Export der Variable '$UserMemberOf' in eine weitere Datei stellt kein Problem dar!?
Möchte jedoch zum Vorgang (Job-ID) nur eine Datei erstellen...
Vielen Dank im Voraus für jede Art der Zusammenarbeit.
Manfred Schüler
Antworten
-
Hi Manfred,
- Wenn du die Werte einzeln zufügst kommen die nicht untereinander sondern nebeneinander an.
- Alternativ zu csv kannst du auch direkte xlsx bauen, indem du Excel als ComObject angräbst
- Schleife ... schwierig ... hm.......
$Result = @() $n = 0 while ($n -lt $UsermemberOf.Count) { if ($n -eq 0) { $props = @{ DisplayName = $ADUser.DisplayName SamAccountName = $ADUser.SamAccountName SID = $ADUser.objectSID.Value MailboxEnabled = $UserMailboxEnabled EmailAddress = $UserEmailAddress MemberOf = $UserMemberOf[$n].SamAccountName MemberOfSID = $UserMemberOf[$n].SID.Value } $Result += New-Object PSObject -Property $props } else { $props = @{ DisplayName = "" SamAccountName = "" SID = "" MailboxEnabled = "" EmailAddress = "" MemberOf = $UserMemberOf[$n].SamAccountName MemberOfSID = $UserMemberOf[$n].SID.Value } $Result += New-Object PSObject -Property $props } $n++ }
:)
Grüße,
Friedrich
There's no place like 127.0.0.1
Alle Antworten
-
Hi Manfred,
aaaalso, erstmal, dein Objekt kann man einfacher und übersichtlicher bauen:
$props = @{ DisplayName = $ADUser.DisplayName SamAccountName = $ADUser.SamAccountName SID = $ADUser.objectSID.Value MailboxEnabled = $UserMailboxEnabled EmailAddress = $UserEmailAddress MemberOf = $UserMemberOf.SamAccountName MemberOfSID = $UserMemberOf.SID.Value } New-Object PSObject -Property $props
dann, passt man das noch im gleichen Zug an, indem man die verschiedenen Werte während der Zuweisung zusammenfügt (ich verwende hier ", " zum Zusammenfügen, jeder andere String funktioniert aber ähnlich gut):
$props = @{ DisplayName = $ADUser.DisplayName SamAccountName = $ADUser.SamAccountName SID = $ADUser.objectSID.Value MailboxEnabled = $UserMailboxEnabled EmailAddress = $UserEmailAddress MemberOf = $UserMemberOf.SamAccountName -join ", " MemberOfSID = $UserMemberOf.SID.Value -join ", " } New-Object PSObject -Property $props
Und schon passt das alles :)
Dann noch zu deinem Export-Csv Aufruf:
- Encoding: Für das lokal übliche Encoding - grade für Sonderzeichen - empfehle ich encoding typ "Default" zu verwenden. Falls das ganze über verschiedene Regionen hinweg verwendet werden soll ist was Festes natürlich erforderlich.
- ErrorAction: Explizit ErrorAction $ErrorActionPreference anzugeben ist redundant - diese wird standardmäßig sowieso verwendet.
- Es ist nicht erforderlich explizit einen Array zu bauen, um diesen an Export-Csv zu übergeben, du kannst auch ein einzelnes Objekt übergeben.
Grüße,
Friedrich
There's no place like 127.0.0.1
- Bearbeitet FWN Dienstag, 29. September 2015 15:17
-
Hallo Friedrich,
danke für deine Unterstützung.
Grundsätzlich "gibt es viele Wege nach Rom" ;-)
Mit meiner PS Erfahrung von ein paar Monaten, suche ich, wie viele andere aber auch, nach dem goldenen Weg nach Rom :-)zu Results:
Dein Vorschlag mit dem "Props" Array habe ich schon öfter genutzt, jedoch dabei festgestellt das dann keine Sortierung der Spaltenüberschrift im CSV-Export erfolgt (Höchstens mit $ResultSort = $Result | sort)
Mit Add-Member kann ich deinen Vorschlag auch realisieren:
$Object = New-Object PSObject -Property Test, Test2 Add-Member -InputObject $Object -memberType NoteProperty -Name DisplayName -Value $ADUser.'DisplayName' Add-Member -InputObject $Object -memberType NoteProperty -Name SamAccountName -Value $ADUser.'SamAccountName' Add-Member -InputObject $Object -memberType NoteProperty -Name SID -Value $ADUser.'objectSID'.Value Add-Member -InputObject $Object -memberType NoteProperty -Name MailboxEnabled -Value $UserMailboxEnabled Add-Member -InputObject $Object -memberType NoteProperty -Name EmailAddress -Value $UserEmailAddress Add-Member -InputObject $Object -memberType NoteProperty -Name LyncEnabled -Value $UserLyncEnabled Add-Member -InputObject $Object -memberType NoteProperty -Name SIPAddress -Value $UserLyncSIP Add-Member -InputObject $Object -memberType NoteProperty -Name MemberOf -Value ($UserMemberOf.SamAccountName -join ", ") Add-Member -InputObject $Object -memberType NoteProperty -Name MemberOfSID -Value ($UserMemberOf.SID.Value -join ", ") #
Ziel (weiß halt nicht ob das überhaupt funktioniert) ist jedoch das die Ergebnisse zum Attribute "MemberOf" in der entsprechende Spalte untereinander ausgelistet werden, was bei einer hohen Anzahl in Excel auch sinnvoll erscheint!?
So wie hier:
Zum Export-CSV
- Ich nutze gerade wegen unseren Umlauten und den internationalen Akzente-Zeichen das UTF8 Format. Ist dies nicht zu empfehlen?
- Die Variable $ErrorActionPreference habe ich im Script (war nicht vollständig aufgeführt) vorab deklariert um diese global bei bedarf ändern zu können.
LG
Manfred Schüler
-
Hi Manfred,
Results
Da hast du natürlich Recht mit der Eigenschaftssortierung, aber erfahrungsgemäß ist das dafür deutlich härter zu warten im Script. Reihenfolge und Darstellung ist in meinen Augen eine Sache, die nur direkt vor Darstellung / Output implementiert werden sollte. Das lässt sich über Select-Object direkt vor dem Export realisieren. Beispiel:$Results | Select DisplayName, SamAccountName, SID, MailboxEnabled, EmailAddress, LyncEnabled, SIPAddress, MemberOf, MemberOfSID | Export-Csv ...
Export-Csv Encoding
"Default" berücksichtigt alle lokalen Gegebenheiten. UTF8 kann zwar auch Umlaute korrekt darstellen, aber dritt-Anwendungen arbeiten oft besser mit den lokalen Encodings. Default funktioniert auch bei Usern mit komplett anderen Schriftsätzen (zb. könntest du das Skript dann einem Chinesischen Kollegen weitergeben).Wie aber gesagt funktioniert es nur innerhalb eines Kulturkreises. Für einen Transfer der Daten von Deutschland - China müsste dann vorraussichtlich explizit ein Encoding gewählt werden (wie UTF8).
ErrorActionPreference
Die Variable existiert bereits beim Start der Konsole. Überschreibst du diese in deinem Script berücksichtigen diese alle Funktionen in der Scope in der das geschieht und in allen Unterscopes. Daher sind diese beiden Befehlsaufrufe synonym:#region Version 1 # Anfang des Scripts $ErrorActionPreference = "SilentlyContinue" # ... # ... # ... # Funktionsaufruf $Results | Export-Csv file.csv -ErrorAction $ErrorActionPreference #endregion Version 1 #region Version 2 # Anfang des Scripts $ErrorActionPreference = "SilentlyContinue" # ... # ... # ... # Funktionsaufruf $Results | Export-Csv file.csv #endregion Version 2
Grüße,
FriedrichThere's no place like 127.0.0.1
-
Hi Friedrich,
wiederum danke für dein Feedback.
Das Thema Error Handling steht noch auf meiner "learning agenda"! :-)
Hast du auch noch eine Idee wie ich die Ausgabe wie oben gezeigt hin bekomme?
Ich weiß, ich bin Anspruchsvoll , aber es reizt mich ...
Manfred Schüler
-
Ach ja, da war ja noch was.
In Csv geht das nur auf eine Weiße:
Du erstellst leere Dummy-Objekte mit allen Eigenschaften leer außer den beiden.Du brauchst also die Anzahl an Zeilen die du benötigst (Länge Gruppenmitgliedschaften). Dann machst du eine Schleife die X-mal läuft, beim ersten mal schreibst du die vollen Werte und die erste Gruppe rein, in allen weiteren Durchläufen dann jeweils leere Strings plus die entsprechend näcshte Gruppe.
Grüße,
FriedrichThere's no place like 127.0.0.1
-
Herrje, das klingt kompliziert ... !
Kann man dem PSCustomObject nicht durch eine Schleife in die Spalte 'MemberOf' (Property) die Werte als Schleife hinzufügen?
Schließlich kann ich die Spalte doch auch direkt ansprechen? $Result.'MemberOf'- "In Csv geht das nur auf eine Weiße"
Was würdest du sonst als Ausgabe nutzen? - Schleife
Der Gedanke mit der Schleife ist auch mein Ansatz, jedoch müsste ich bei verschiedenen Werte.Counts den höchsten erst einmal ermitteln und das scheint mir nun doch zu schwierig :-(
$InterimResults = ForEach ($obj in $UserMemberOf) { New-Object -TypeName PSObject -Property @{ 'DisplayName' = $ADUser.'DisplayName' 'SamAccountName' = $ADUser.'SamAccountName' 'MailboxEnabled' = $UserMailboxEnabled 'EmailAddress' = $UserEmailAddress 'MemberOf' = $obj.SamAccountName 'MemberOfSID' = $obj.SID.Value } }
Manfred Schüler
- "In Csv geht das nur auf eine Weiße"
-
Hi Manfred,
- Wenn du die Werte einzeln zufügst kommen die nicht untereinander sondern nebeneinander an.
- Alternativ zu csv kannst du auch direkte xlsx bauen, indem du Excel als ComObject angräbst
- Schleife ... schwierig ... hm.......
$Result = @() $n = 0 while ($n -lt $UsermemberOf.Count) { if ($n -eq 0) { $props = @{ DisplayName = $ADUser.DisplayName SamAccountName = $ADUser.SamAccountName SID = $ADUser.objectSID.Value MailboxEnabled = $UserMailboxEnabled EmailAddress = $UserEmailAddress MemberOf = $UserMemberOf[$n].SamAccountName MemberOfSID = $UserMemberOf[$n].SID.Value } $Result += New-Object PSObject -Property $props } else { $props = @{ DisplayName = "" SamAccountName = "" SID = "" MailboxEnabled = "" EmailAddress = "" MemberOf = $UserMemberOf[$n].SamAccountName MemberOfSID = $UserMemberOf[$n].SID.Value } $Result += New-Object PSObject -Property $props } $n++ }
:)
Grüße,
Friedrich
There's no place like 127.0.0.1
-
Hallo Manfred, ist dein Problem damit gelöst? Dann markiere doch bitte entsprechend die Antworten.
Grüße, Denniver
Blog: http://bytecookie.wordpress.com
Kostenloser Powershell Snippet Manager v4: Link ! Neue Version !
(Schneller, besser + komfortabler scripten.)
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. -
Hallo Friedrich,
sorry leider etwas verspätet, habe mir gerade dein PS Code angeschaut und ausgeführt.
Nutze ich diesen wie beschrieben, erhalte ich keine Ergebnisse in der Variable "$Result".
Ändere ich deinen Code wie folgt ab, kommt genau mein gewünschtes Ergebnis zustande, SUPER :-) TOP!!!
$Result = @() $n = 0 # while ($n -lt $UsermemberOf.Count) { if ($n -eq 0) { $props = @{ DisplayName = $ADUser.DisplayName SamAccountName = $ADUser.SamAccountName SID = $ADUser.objectSID.Value MailboxEnabled = $UserMailboxEnabled EmailAddress = $UserEmailAddress MemberOf = $UserMemberOf[$n].SamAccountName MemberOfSID = $UserMemberOf[$n].SID.Value } $Result += New-Object PSObject -Property $props } else { $props = @{ DisplayName = "" SamAccountName = "" SID = "" MailboxEnabled = "" EmailAddress = "" MemberOf = $UserMemberOf[$n].SamAccountName MemberOfSID = $UserMemberOf[$n].SID.Value } $Result += New-Object PSObject -Property $props } $n++ }
Geändert habe ich nur die While Bedingung
# $UsermemberOf in $UsermemberOf.Count
Bin mir zwar nicht sicher, ob das Syntax technisch in Ordnung ist, aber so funktioniert die Ausgabe $False/$True besser und zudem dann auch das Ergebnis.
Wieder was dazu gelernt ;-)
Dir im speziellen vielen Dank und evtl. Gruß an die MS Programmierer, bei Arrays ggf. horizontal und vertikal Werte setzen zu können ... aber vermutlich bin ich eher das Problem :-)
Manfred Schüler
- Bearbeitet MSchueler Dienstag, 6. Oktober 2015 15:11
-
Hi Manfred,
freut mich, dass das jetzt alles funktioniert.
Bezüglich multidimensionaler Arrays, probier mal das hier:
[int[][]]$a = new-object int[][](10,10) $a[0][1] = 42
Funktioniert einwandfrei. Das Problem hier ist das CSV Format, das schlicht nicht dafür gedacht ist. Für multiline Darstellung könnte html guten Output anbieten, Excel Spreadsheets oder XML eignen sich aber auch.
Letzten Endes ist es ja primär eine Frage des Konsummentens.
Grüße,
Friedrich
There's no place like 127.0.0.1
- Bearbeitet FWN Dienstag, 6. Oktober 2015 16:09 Replaced "new" with "new-object", "new" being a custom alias ...
-
Hi Friedrich,
ich verstehe langsam ... sehr langsam
[int[][]]$a = new-object int[][](5,5) $a[0][0] = 42 $a[1][0] = 24 $a[2][0] = 44 $a[3][0] = 22 $a[4][0] = 12 $a | Export-csv -Path C:\Temp\Output.csv -NoTypeInformation $a | Export-Clixml -Path C:\Temp\Output.xml
Im XML sind auch die Werte zu sehen, im CSV nicht.
Ist der Aufbau grundsätzlich auch, statt mit einem Zahlen Array, wie in Excel SpaltenName, ZeilenInhalt möglich?
Manfred Schüler
-
Hi Manfred,
das ist genau der Punkt: Csv kann so etwas nicht wirklich nativ abbilden. Die oben beschriebene Methode mit Dummy-Objekten ist da leider der einzige Weg.
Für Export mit Xml kannst du dein originales Objekt, mit Array Eigenschaften, verwenden. multidimensionale Arrays sind eher eine Spielerei, die in PowerShell meist nicht notwendig sind (du könntest aber zb ein Schachspiel darüber abbilden, oder Schiffe versenken).
Wenn du andere Inhalte als nur Zahlen in einem multidimensionalen Array verwenden willst, dann kannst du den Array als "Object" deklarieren, statt als "int". Daraufhin kannst du einfach alles reinschieben was dir gefällt.
Excel Tabellen direkt befüllen ist auch gut möglich, wenn du das wirklich willst, erfordert aber deutlich mehr Aufwand.
Tip: Funktionen
Falls du wirklich häufiger vor dem Problem hier stehst, empfehle ich eine maßgeschneiderte Export-CsvCustom Funktion zu schreiben, die den Vorgang oben für dich abbildet, also Dummy-Objekte erstellt und das Ganze exportiert. Die kann man dann recht simpel wiederverwenden.Grüße,
FriedrichThere's no place like 127.0.0.1