PowerShell AD-Benutzer (Gruppen entziehen, OU verschieben, Account deaktivieren)

_nero_

Ensign
Registriert
Juli 2009
Beiträge
158
Hi zusammen,

ich bin am verzweifeln und brauche bitte eure Hilfe.
Meine PowerShell Skills reichen leider dafür nicht aus.

Mit dem folgenden Skript:

PowerShell:
Get-ADUser -Identity Username -Properties MemberOf | ForEach-Object {$_.MemberOf | Remove-ADGroupMember -Members $._DistinguishedName -Confirm:$false} |
Move-ADObject -TargetPath "OU=Test,DC=Test,DC=net" -PassThru | Disable-ADAccount

würde ich gerne erreichen, dass PowerShell den User (Username) ausliest, alle seine Gruppen entfernt, in eine bestimmte OU verschiebt und anschließend den Account deaktiviert.
Die Gruppen werden aktuell alle entfernt, aber leider wird der User nicht in die OU geschoben und bleibt auch weiterhin aktiviert.

Vorhin bei diversen Anpassungen am Skript habe ich es geschafft, dass die User verschoben und deaktiviert wurden. Jedoch wurden die Gruppen nicht entfernt..

Wäre toll wenn ein PowerShell Pro mir kurz helfen könnte. Vielen Dank! :D
 
Zuletzt bearbeitet:
_nero_ schrieb:
Get-ADUser -Identity Username -Properties MemberOf | ForEach-Object {$_.MemberOf | Remove-ADGroupMember -Members $._DistinguishedName -Confirm:$false} | Move-ADObject -TargetPath "OU=Test,DC=Test,DC=net" -PassThru | Disable-ADAccount
Wird nicht klappen, einfach alles per Pipe verbinden.

Wenn ich grad keinen Denkfehler gemacht habe, könnte es so als Einzeiler klappen:
Code:
Get-ADUser -Identity Username -Properties MemberOf | ForEach-Object {$_.MemberOf | Remove-ADGroupMember -Members $._DistinguishedName -Confirm:$false; $_.MemberOf | Move-ADObject -TargetPath "OU=Test,DC=Test,DC=net" -PassThru; $_.MemberOf | Disable-ADAccount}

Und alternativ mit Variable (dürfte besser zu erkennen sein):
Code:
$user = Get-ADUser -Identity Username -Properties MemberOf
$user | ForEach-Object {
$_.MemberOf | Remove-ADGroupMember -Members $._DistinguishedName -Confirm:$false
$_.MemberOf | Move-ADObject -TargetPath "OU=Test,DC=Test,DC=net" -PassThru
$_.MemberOf | Disable-ADAccount}

Nach nochmaligem Lesen eher das:
Code:
$user = Get-ADUser -Identity Username -Properties MemberOf
$user | ForEach-Object {$_.MemberOf | Remove-ADGroupMember -Members $._DistinguishedName -Confirm:$false}
$user | Move-ADObject -TargetPath "OU=Test,DC=Test,DC=net" -PassThru
$user | Disable-ADAccount
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: _nero_
Das von kartoffelpü sollte so funktionieren.

Dein Fehler war, dass du den Output von "ForEach-Object {$_.MemberOf | Remove-ADGroupMember -Members $._DistinguishedName -Confirm:$false}" an Move-ADObject übergeben wolltest und den Output davon an Disable-ADAccount.
Dein ForEach gibt aber nichts aus, also wird auch nichts übergeben.

Generell würde ich für bessere Lesbarkeit bei Befehlen die du häufiger brauchst versuchen auf Einzeiler zu verzichten und ein richtiges Snippet daraus machen.

In deinem Beispiel wäre das z.B.
PowerShell:
$users = Get-ADUser -Identity Username -Properties MemberOf
$users | ForEach-Object {$_.MemberOf | Remove-ADGroupMember -Members $._DistinguishedName -Confirm:$false}
$users | Move-ADObject -TargetPath "OU=Test,DC=Test,DC=net"
$users | Disable-ADAccount
 
  • Gefällt mir
Reaktionen: _nero_
Renegade334 schrieb:
Das von kartoffelpü sollte so funktionieren.

Dein Fehler war, dass du den Output von "ForEach-Object {$_.MemberOf | Remove-ADGroupMember -Members $._DistinguishedName -Confirm:$false}" an Move-ADObject übergeben wolltest und den Output davon an Disable-ADAccount.
Dein ForEach gibt aber nichts aus, also wird auch nichts übergeben.

Generell würde ich für bessere Lesbarkeit bei Befehlen die du häufiger brauchst versuchen auf Einzeiler zu verzichten und ein richtiges Snippet daraus machen.

In deinem Beispiel wäre das z.B.
PowerShell:
$users = Get-ADUser -Identity Username -Properties MemberOf
$users | ForEach-Object {$_.MemberOf | Remove-ADGroupMember -Members $._DistinguishedName -Confirm:$false}
$users | Move-ADObject -TargetPath "OU=Test,DC=Test,DC=net"
$users | Disable-ADAccount

Oh man, vielen vielen Dank euch! Ich war so verzweifelt, aber das macht jetzt Sinn. :D

Es funktioniert jetzt auch alles, ich habe "$._DistinguishedName" entfernt und auch hier "Username" genommen. Ist das legitim?

Ich nutze das Power Shell Skript mit Power Automate Desktop und werde die Variable %Username% verwenden. Also "Get-ADUser -Identity %Username%" und ... "Remove-ADGroupMember -Members %Username%"

Auf jeden Fall gehts so. :D
 
Zuletzt bearbeitet:
Wenn es damit geht, ist doch alles gut :)
Falls du dich mehr mit Powershell-Scripting beschäftigen willst, kann ich zum Debugging die alte "Quest PowerGUI" empfehlen, auch wenn es die nur noch bei diversen Downloadseiten gibt, denen ich normalerweise fern bleibe (z.B. Chip, PC Welt etc).

Da kann man gut alle Eigenschaften etc von Variablen, Arrays und Co erkennen, ganz simples Beispiel:
1638904618900.png


Finde ich deutlich angenehmer als die PS ISE...
 
  • Gefällt mir
Reaktionen: _nero_ und ryan_blackdrago
kartoffelpü schrieb:
Wenn es damit geht, ist doch alles gut :)
Falls du dich mehr mit Powershell-Scripting beschäftigen willst, kann ich zum Debugging die alte "Quest PowerGUI" empfehlen, auch wenn es die nur noch bei diversen Downloadseiten gibt, denen ich normalerweise fern bleibe (z.B. Chip, PC Welt etc).

Da kann man gut alle Eigenschaften etc von Variablen, Arrays und Co erkennen, ganz simples Beispiel:
Anhang anzeigen 1156348

Finde ich deutlich angenehmer als die PS ISE...

Ja, das muss halt konsistent sein. Wird öfters genutzt. :)

Danke, das sieht um einiges besser aus. :D
 
Bezüglich IDE:
Habe auch mit Quest PowerGUI angefangen (das wurde zwischendurch von Dell gekauft).
Danach habe ich die standard ISE mit ISESteroids genutzt, aber inzwischen ist die empfohlene Umgebung VSCode mit PowerShell Plugin. Wenn ich mich nicht irre haben die anderen beiden auch keinen Support für neuere PowerShell Versionen (z.B. PowerShell 7) mehr und bekommen den auch nicht.

DistinguishedName durch Username (also quasi SamAccountName) zu ersetzen macht aber eigentlich keinen Sinn.
Bei "Get-ADUser -Identity Username -Properties MemberOf" darf Username vieles sein. Da ist es egal, ob du den DN, SAMAccountName, oder sogar die SID nutzt (einfach $username durch "[System.Security.Principal.WindowsIdentity]::GetCurrent().Name" ersetzen, dann bekommst du "domain\user" als Ergebnis.
Bei "$.DistinguishedName" (haben wir alle den Schreibfehler mitkopiert? Das müsste doch eigentlich $.DistinguishedName heißen...) bekommt der trotzdem den richtigen Namen.

Bei genauerer Überlegung macht das aber auch keinen Sinn.
PowerShell:
$user = Get-ADUser -Identity ([System.Security.Principal.WindowsIdentity]::GetCurrent().Name) -Properties MemberOf
$user.MemberOf | Remove-ADGroupMember -Members $user -Confirm:$false}
$user | Move-ADObject -TargetPath "OU=Test,DC=Test,DC=net"
$user | Disable-ADAccount
Das sollte eigentlich auch funktionieren...müsstest du mal testen :)

Achtung, das führt das bei dem angemeldeten User durch!
Wobei da glaube ich ein Denkfehler vorliegt, weil der User nicht die Rechte dafür haben sollte...
 
PowerShell:
Get-ADPrincipalGroupMembership -Identity $userName | where {$_.name -ne 'Domain Users'} | % {Remove-ADPrincipalGroupMembership -Identity $userName -MemberOf $_ -Confirm:$false}

 
Write-Host "$username wird in Deaktivierte User verschoben"
Get-ADUser $userName | Move-ADObject -TargetPath 'OU=Deaktivierte Accounts,DC=test,DC=test'

Write-Host "$userName wird deaktiviert"
Disable-ADAccount -Identity $userName

Ihr macht euch das zu schwer :)
Das Domain Users kann natürlich auch rausgeschmissen werden.


PowerShell:
#Dieses Skript exportiert alle Gruppenzugehörigkeiten und den "Distinguished Name" in eine CSV Datei. Anschließend wird der User deaktiviert und in die OU Deaktivierte User verschoben.
#Der Dateiname setzt sich dann aus dem komplettenNamen des deaktivierten Users und dem Datum zusammen, an dem dieses Script ausgeführt wurde.

#Windows Forms Assembly laden
Add-Type -AssemblyName System.Windows.Forms

cls

#Optionale Information. Kurzbeschreibung und Ersteller des Scriptes
Write-Host "User deaktivieren und verschieben"

#Funktion zur Anzeige eines Eingabedialoges fuer den Namen des Mitarbeiters
function ReadOU-InputBoxDialog([string]$Message, [string]$WindowTitle, [string]$DefaultText)
{     
    Add-Type -AssemblyName Microsoft.VisualBasic
    return [Microsoft.VisualBasic.Interaction]::InputBox($Message, $WindowTitle, $DefaultText)
}

$yesno = [System.Windows.Forms.MessageBox]::Show("Das Exchange-Postfach muss vor der Ausführung dieses Skriptes verschoben werden. Ist das Exchange-Postfach bereits verschoben worden?","Hinweis",[System.Windows.Forms.MessageBoxButtons]::YesNo)
if ($yesno -eq [Windows.Forms.DialogResult]::Yes)
{
    #Optionale Information. Laden des Active Directory Moduls
    Write-Host "Active Directory Modul wird geladen..."
    Import-Module ActiveDirectory
    ##########################################
    ##             CSV Export               ##
    ##########################################

    #Abfrage des Mitarbeiternamens. Das Format muss vorname.nachname sein.
    if ($userName = ReadOU-InputBoxDialog -Message "Bitte vorname.nachname eingeben." -WindowTitle "Vorname.Nachname" -ne [Windows.Forms.DialogResult]::Abort)
    {
        
        if ($ticketnummer = ReadOU-InputBoxDialog -Message "Bitte Ticketnummer eingeben. Z.B.: 123456" -WindowTitle "Ticketnummer" -ne [Windows.Forms.DialogResult]::Abort)
        {

            #Benötigte Variablen
            $dateToday = (Get-Date).ToString('dd-MM-yyyy')
            $fileName = "$username" + "_" + "$dateToday.csv"
            $pfad = "T:"


            # Custom Objekt für die CSV Tabelle anlegen
            $newrow = New-Object PSObject -Property @{
               distinguishedName = ""
               Name = ""
            }

            # Export nach CSV
            Write-Host "CSV Datei wird exportiert..."
            $newrow | Export-CSV "$pfad$fileName" -notypeinformation -Delimiter ";"
            $user = Get-ADUser $userName | Select distinguishedName | Export-CSV "$pfad$fileName" -notypeinformation -Append -Force -Delimiter ";"
            $gruppen = Get-ADPrincipalGroupMembership -Identity $userName | Select Name | Export-CSV "$pfad$fileName" -notypeinformation -append -Force -Delimiter ";"

            #Testen, ob Datei erfolgreich erstellt wurde
            if (Test-Path "$pfad$fileName")
            {
                Write-Host $fileName " in " $pfad " erstellt."

                #Information über die Erstellung einer CSV Datei.
                [System.Windows.Forms.MessageBox]::Show($fileName + " in " + $pfad + " erstellt.","Fertig",[System.Windows.Forms.MessageBoxButtons]::OK)
            }
            else
            {
                [System.Windows.Forms.MessageBox]::Show("Fehler! Keine CSV Datei erstellt.","Fehler",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Error)
                Exit
            }

            ########################################################
            ## Gruppen löschen, User verschieben und deaktivieren ##
            ########################################################

            Write-Host "Gruppen von $username werden gelöscht"
            Get-ADPrincipalGroupMembership -Identity $userName | where {$_.name -ne 'Domain Users'} | % {Remove-ADPrincipalGroupMembership -Identity $userName -MemberOf $_ -Confirm:$false}

    
            Write-Host "$username wird in Deaktivierte User verschoben"
            Get-ADUser $userName | Move-ADObject -TargetPath 'OU=Deaktivierte Accounts,DC=test,DC=test'

            Write-Host "$userName wird deaktiviert"
            Disable-ADAccount -Identity $userName

            Write-Host "Beschreibung von $userName wird angepasst"
            get-aduser $userName -Properties Description | ForEach-Object { Set-ADUser $_ -Description "$($_.Description) DEAKTIVIERT #$ticketnummer" }

    
Write-Host "Script Ende"
Write-Host "==========="
$yesNoCloseWindows = Read-Host "Fenster schließen? y/n: "
if ($yesNoCloseWindows -eq "y")
{
    Exit
}
else
{
    Read-Host
}
        }
        else
        {
            [System.Windows.Forms.MessageBox]::Show("Abbrechen geklickt! Keine CSV Datei erstellt.","Abbruch",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Exclamation)
            Exit
        }
    }
    
    else
    {
        [System.Windows.Forms.MessageBox]::Show("Abbrechen geklick Keine CSV Datei erstellt.","Abbruch",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Exclamation)
        Exit
    }
}
else
{
    [System.Windows.Forms.MessageBox]::Show("Abbruch. Bitte erst das Exchange Postfach verschieben.","Fehler",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Exclamation)
    Exit
}

So sieht dann unser ganzes Script aus
 
Zurück
Oben