Benutzer mit den meisten Antworten
Compare-Object txt-file & Variable

Frage
-
## Script zum Versenden von Änderungen an den ## Gruppenzugehörigkeiten der Gruppen ## "Domain Admins" und "Administrators" ## Zwischenspeicher des letzten Standes $lastresultfolder = "C:\TEMP\admins.txt" ### E-Mail Variablen: ## Deklarieren des E-Mail Empfängers $xemail = "HierEinName@domain.com" ## Deklarieren des E-Mail Absenders $xabsender = "PowerShell@domain.local" ## Deklarieren des E-Mail Betreffs $xbetreff = "Administratoren - Accounts" ## Deklarieren des E-Mail Inhalts $xinhalt = ("Änderungen an den Administrator Berechtigungen: "+$compare+"Aktueller Stand: "+$newresult+"Letzter Stand: "+$lastresult) ## Deklarieren des SMTP-Servers $xsmtp = "smtp.domain.local" ## Test, ob ein letzter Stand existiert. $TestP = (Test-Path $lastresultfolder) ## Wenn kein letzter Stand vorhanden ist, ## wird die .txt erstellt. if($TestP -eq 0){ New-Item $lastresultfolder -type file } ## letzten Stand auslesen $lastresult = (Get-Content $lastresultfolder) ## Aktuelle Administratoren auslesen $domainadmins = (Get-ADGroupMember -Identity "Domain Admins" | %{$_.SamAccountName+" - "+$_.name+"`n"}) $admins = (Get-ADGroupMember -Identity "Administrators" | %{$_.SamAccountName+" - "+$_.name+"`n"}) $newresult = "`nFolgende User sind in der Gruppe Domain Admins:`n`n"+$domainadmins+"`n`nFolgende User sind in der Gruppe Administrators:`n`n"+$admins ## letzten Stand mit aktuellem Stand vergleichen $compare = (Compare-Object -referenceObject $lastresult -differenceObject $newresult -IncludeEqual) ## Versenden der E-Mail #Send-MailMessage -to $xemail -from $xabsender -Subject $xbetreff -body $xinhalt -SmtpServer $xsmtp Write-Host $compare ## Aktuellen Stand speichern $newresult | Out-File $lastresultfolder
Dieses Skript habe ich geschrieben, um die aktuellen Veränderungen der Gruppen "Domain Admins" und "Administrators" zu dokumentieren. Leider scheint Compare-Object hier nicht zu funktionieren oder ich habe einen Fehler gemacht, den ich besten Willens nicht erkennen kann, denn er zeigt mir bei der Auswertung immer alle Daten an, nicht nur die Unterschiede zwischen den Variablen.
Wenn jemand Ideen hat, sind die sehr willkommen. :)
Lieber Gruß,
Grunch
Antworten
-
Ich würde diese Aufgabe etwas anders angehen .... hier also mal ein Vorschlag:
$TimeStamp = Get-Date -Format 'yyyy-MM-dd_HH-mm-ss' $ResultRoot = 'C:\temp' Get-ADGroupMember -Identity 'Administrators' -OutVariable CurrentAdministratoren | Export-Clixml -Path (Join-Path -Path $ResultRoot -ChildPath ('Admins_' + $TimeStamp + '.xml')) -Encoding UTF8 Get-ADGroupMember -Identity 'Domain Admins' -OutVariable CurrentDomainAdmins | Export-Clixml -Path (Join-Path -Path $ResultRoot -ChildPath ('DomainAdmins_' + $TimeStamp + '.xml')) -Encoding UTF8 Get-ChildItem -Path $ResultRoot -Filter 'Admins*.xml' | Sort-Object -Property BaseName | Select-Object -Last 2 -OutVariable AdminFiles Get-ChildItem -Path $ResultRoot -Filter 'DomainAdmins*.xml' | Sort-Object -Property BaseName | Select-Object -Last 2 -OutVariable DomainAdminFiles $AdminResult = Compare-Object -ReferenceObject (Import-Clixml -Path $AdminFiles[0].FullName) -DifferenceObject (Import-Clixml -Path $AdminFiles[1].FullName) -Property SamAccountName -IncludeEqual -PassThru $DomainAdminResult = Compare-Object -ReferenceObject (Import-Clixml -Path $DomainAdminFiles[0].FullName) -DifferenceObject (Import-Clixml -Path $DomainAdminFiles[1].FullName) -Property SamAccountName -IncludeEqual -PassThru $AdminResult | Select-Object -Property SamAccountName,Name,SideIndicator | Format-Table -AutoSize $DomainAdminResult | Select-Object -Property SamAccountName,Name,SideIndicator | Format-Table -AutoSize
... und hier ein paar Erklärungen dazu:
Ich habe mich mal auf die eigentliche Kernaufgabe konzentriert und den Email-Kram weggelassen. ich bin kein Freund von zu viel schmückendem Beiwerk in eigentlich technischen Informationen/Daten. Deshalb hab ich deine "Texte"/"Erklärungen" auch weggelassen. Die kannst Du ja, wenn nötig, als Header in der Email platzieren ....
Ich halte es für weniger robust oder zuverlässig, aus Objekten extrahierte und in Strings umgewandelte Werte zu vergleichen. Ich denke, wenn wir schon die Powershell benutzen und deren Mehrwert richtige Objekte sind, dann sollten wir die auch nutzen. Das halte ich auch für deutlich flexibler.
... und noch'n Tipp für Deine Formatierungen. Da die Powershell-Syntax quasi selbst-dokumentierend ist, machen Kommentare, die die gut lesbaren nächsten zwei Code-Zeilen nochmal kommentieren, den Code eher unübersichtlich und blähen ihn auf. Übermäßig viele Leerzeilen sind, speziell hier im Forum, auch eher hinderlich, genau wie Aliasse oder Abkürzungen. Einrückungen sollten möglichst die Code-Struktur abbilden/unterstützen (Schleifen und Bedingungen).Die Ausgabe am Schluss kann natürlich nach Belieben verändert werden. Dadurch, dass es die unveränderten Objekte sind, kannst Du sie einmal als Tabelle auf der Konsole ausgeben, als GridView z.B. so:
$AdminResult | Out-GridView $DomainAdminResult | Out-GridView
.... oder eben als html-formatierte Mail für den Chef. ;-)
Grüße - Best regards
PS:> (79,108,97,102|%{[char]$_})-join''
Alle Antworten
-
Ich würde diese Aufgabe etwas anders angehen .... hier also mal ein Vorschlag:
$TimeStamp = Get-Date -Format 'yyyy-MM-dd_HH-mm-ss' $ResultRoot = 'C:\temp' Get-ADGroupMember -Identity 'Administrators' -OutVariable CurrentAdministratoren | Export-Clixml -Path (Join-Path -Path $ResultRoot -ChildPath ('Admins_' + $TimeStamp + '.xml')) -Encoding UTF8 Get-ADGroupMember -Identity 'Domain Admins' -OutVariable CurrentDomainAdmins | Export-Clixml -Path (Join-Path -Path $ResultRoot -ChildPath ('DomainAdmins_' + $TimeStamp + '.xml')) -Encoding UTF8 Get-ChildItem -Path $ResultRoot -Filter 'Admins*.xml' | Sort-Object -Property BaseName | Select-Object -Last 2 -OutVariable AdminFiles Get-ChildItem -Path $ResultRoot -Filter 'DomainAdmins*.xml' | Sort-Object -Property BaseName | Select-Object -Last 2 -OutVariable DomainAdminFiles $AdminResult = Compare-Object -ReferenceObject (Import-Clixml -Path $AdminFiles[0].FullName) -DifferenceObject (Import-Clixml -Path $AdminFiles[1].FullName) -Property SamAccountName -IncludeEqual -PassThru $DomainAdminResult = Compare-Object -ReferenceObject (Import-Clixml -Path $DomainAdminFiles[0].FullName) -DifferenceObject (Import-Clixml -Path $DomainAdminFiles[1].FullName) -Property SamAccountName -IncludeEqual -PassThru $AdminResult | Select-Object -Property SamAccountName,Name,SideIndicator | Format-Table -AutoSize $DomainAdminResult | Select-Object -Property SamAccountName,Name,SideIndicator | Format-Table -AutoSize
... und hier ein paar Erklärungen dazu:
Ich habe mich mal auf die eigentliche Kernaufgabe konzentriert und den Email-Kram weggelassen. ich bin kein Freund von zu viel schmückendem Beiwerk in eigentlich technischen Informationen/Daten. Deshalb hab ich deine "Texte"/"Erklärungen" auch weggelassen. Die kannst Du ja, wenn nötig, als Header in der Email platzieren ....
Ich halte es für weniger robust oder zuverlässig, aus Objekten extrahierte und in Strings umgewandelte Werte zu vergleichen. Ich denke, wenn wir schon die Powershell benutzen und deren Mehrwert richtige Objekte sind, dann sollten wir die auch nutzen. Das halte ich auch für deutlich flexibler.
... und noch'n Tipp für Deine Formatierungen. Da die Powershell-Syntax quasi selbst-dokumentierend ist, machen Kommentare, die die gut lesbaren nächsten zwei Code-Zeilen nochmal kommentieren, den Code eher unübersichtlich und blähen ihn auf. Übermäßig viele Leerzeilen sind, speziell hier im Forum, auch eher hinderlich, genau wie Aliasse oder Abkürzungen. Einrückungen sollten möglichst die Code-Struktur abbilden/unterstützen (Schleifen und Bedingungen).Die Ausgabe am Schluss kann natürlich nach Belieben verändert werden. Dadurch, dass es die unveränderten Objekte sind, kannst Du sie einmal als Tabelle auf der Konsole ausgeben, als GridView z.B. so:
$AdminResult | Out-GridView $DomainAdminResult | Out-GridView
.... oder eben als html-formatierte Mail für den Chef. ;-)
Grüße - Best regards
PS:> (79,108,97,102|%{[char]$_})-join'' -
> Ich würde diese Aufgabe etwas anders angehen ....
Und ich würde das noch mal anders machen :-)
Aktiviere Auditing - DS Access - Verzeichnisdienständerungen überwachen. Dann aktiviere in den Sicherheitseinstellungen der beiden Gruppen die Überwachung "Jeder" - "Alle Eigenschaften schreiben" (ist standardmäßig aktiviert...)
Ab jetzt wird auf dem ausführenden Domain Controller ein Security Audit Event erzeugt, wenn jemand "egal was" an diesen Gruppen ändert.
Die Events, die Dich interessieren, findest Du in https://support.microsoft.com/de-de/help/977519/description-of-security-events-in-windows-7-and-in-windows-server-2008Der Rest ist eine Fingerübung: Entweder Skript an die Events binden oder Event Forwarding einrichten. Oder Ihr habt schon eine entsprechende Lösung im Einsatz, dann da einbinden.
-
Und noch ein Kommentar zur ursprünglichen Frage:
$compare = (Compare-Object -referenceObject $lastresult -differenceObject $newresult -IncludeEqual)
zeigt mir bei der Auswertung immer _alle_Daten an, nicht nur die Unterschiede zwischen den Variablen.Na, was denkst Du, was "-IncludeEqual" genau bewirkt? :-)
-
Nee nee nee ... das gilt nicht!! Wir suchen hier POWERSHELL-Lösungen!!! :-D ;-)
Ja, manchmal übersieht man (ich), dass die beste Lösung für ein Script einfach kein Script ist. Und robuster/zuverlässiger isses wahrscheinlich auch noch.
Grüße - Best regards
PS:> (79,108,97,102|%{[char]$_})-join'' -
> Nee nee nee ... das gilt nicht!! Wir suchen hier POWERSHELL-Lösungen!!! :-D ;-)
Oft hilft es, einen Schritt zurück zu treten und sich die Anforderung noch mal genau anzuschauen :) Viele Threads hier entstehen, weil sich der TO vorher zu wenig um die generellen Fragen kümmerte und sofort ins technische einsteigt.
Ich habe gelernt: Je besser Du Pflichtenheft und Fachkonzept ausarbeitest, um so schneller bist Du hinterher mit der Umsetzung fertig. Und "insgesamt" geht es immer noch deutlich schneller.
Um das auf diesen Thread zu übertragen: Die Frage hätte nicht "Compare-Object" sein dürfen, sondern "Wie überwache ich Gruppenmitgliedschaften". Und das mit den LastResult finde ich eh nicht prickelnd - wenn das entsorgt wird, geht alles schief :)
PS: Um noch was produktives zu sagen - wenn ich PoSh-Objekte in Dateien speichern will, nehme ich dafür gerne Export/Import-CliXML. Dann werden das beim Importieren nämlich wieder die ursprünglichen Objekte, und damit kann Compare-Object besser umgehen als im Fall des TO, wo nur String-Arrays verglichen werden.