GitHub GitHub Hover Bluesky Bluesky Hover Medium Medium Hover CodePen CodePen Hover YouTube YouTube Hover

Mehrere AD-Benutzer automatisch per PowerShell aus CSV anlegen

Active Directory: Mehrere Benutzer automatisch per PowerShell aus CSV anlegen (inkl. Umlaute, Dubletten, Logging)

Wenn du regelmäßig neue Benutzer in AD anlegen musst (1 oder 100), ist PowerShell + CSV die sauberste Lösung. Du sparst Zeit, vermeidest Tippfehler und bekommst gleich ein Log, was wirklich passiert ist.

In diesem Artikel zeige ich eine praxistaugliche „Admin-Version“ mit:

  • CSV-Import (GivenName, Surname)
  • automatischem Login nach Schema vorname.nachname
  • Umlaut-Umschreibung (Jörg Weiß → joerg.weiss)
  • Dubletten-Check (wenn es den Login schon gibt → noah.fischer2, noah.fischer3 …)
  • zufälligem Startpasswort
  • optionaler verschlüsselter Passwort-Export (nicht im Klartext)
  • Log-Datei für Nachvollziehbarkeit

Voraussetzungen

  • Du führst das Script auf einem PC/Server aus, der die RSAT AD Tools hat oder direkt auf dem DC.
  • PowerShell als Administrator starten.
  • Du hast Rechte, Benutzer in der Ziel-OU anzulegen.

1) CSV vorbereiten

Erstelle users.csv in z.B. C:\Users\bauer.AD\Documents

Inhalt:

GivenName,Surname
Noah,Fischer
Jörg,Weiß
Mia,Weber

Wichtig:

  • Spalten heißen exakt GivenName und Surname
  • Standard ist Komma als Trennzeichen. Wenn Excel bei dir Semikolon nutzt, stellen wir das im Script um.

2) Ziel-OU prüfen

Die Benutzer sollen bei dir nach:

rubinhood → Users

Also:

OU=Users,OU=rubinhood,DC=ad,DC=rubinhood,DC=de

Wenn du sicher sein willst:

Get-ADOrganizationalUnit -Filter 'Name -eq "Users"' | Select Name, DistinguishedName

3) PowerShell Script (Profi-Version)

✅ Dieses Script ist bewusst so gebaut, dass es auch in der Konsole funktioniert (ohne $PSScriptRoot), weil Leute gern alles in C:\Windows\System32 ausführen und sich dann wundern.

Du musst nur $BaseFolder anpassen (wo users.csv liegt).

Import-Module ActiveDirectory

# ========== Konfiguration ==========
$OU        = "OU=Users,OU=rubinhood,DC=ad,DC=rubinhood,DC=de"
$UpnSuffix = "ad.rubinhood.de"

# Ordner, wo users.csv liegt (anpassen!)
$BaseFolder = "C:\Users\bauer.AD\Documents"

$CsvPath = Join-Path $BaseFolder "users.csv"
$CsvDelimiter = ","  # falls Excel Semikolon: ";"

# Log-Dateien (mit Timestamp)
$Stamp   = Get-Date -Format "yyyyMMdd_HHmmss"
$LogFile = Join-Path $BaseFolder "ADUserCreate_$Stamp.log"

# Optional: verschlüsselte Passwortliste (nur auf diesem Windows-User entschlüsselbar)
$EnableEncryptedPasswordExport = $true
$EncryptedPwFile = Join-Path $BaseFolder "InitialPasswords_$Stamp.clixml"

# ========== Hilfsfunktionen ==========
function Write-Log {
    param(
        [string]$Message,
        [ValidateSet("INFO","WARN","ERROR")] [string]$Level = "INFO"
    )
    $line = "{0} [{1}] {2}" -f (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $Level, $Message
    Add-Content -Path $LogFile -Value $line -Encoding UTF8
}

function Normalize-LoginPart {
    param([string]$s)

    if ([string]::IsNullOrWhiteSpace($s)) { return "" }

    $s = $s.Trim().ToLower()

    # Umlaute/ß ersetzen
    $s = $s.Replace("ä","ae").Replace("ö","oe").Replace("ü","ue").Replace("ß","ss")

    # Sonderzeichen entfernen (erlaubt: a-z, 0-9, punkt)
    $s = $s -replace "[^a-z0-9\.]", ""

    # Mehrere Punkte zusammenfassen, Punkt am Anfang/Ende entfernen
    $s = $s -replace "\.+", "."
    $s = $s.Trim(".")

    return $s
}

function New-RandomPassword {
    param([int]$Length = 14)

    if ($Length -lt 10) { $Length = 10 }

    $upper   = "ABCDEFGHJKLMNPQRSTUVWXYZ"
    $lower   = "abcdefghijkmnopqrstuvwxyz"
    $digits  = "23456789"
    $special = "!@#$%*?-_"

    $chars = @()
    $chars += ($upper.ToCharArray()   | Get-Random -Count 1)
    $chars += ($lower.ToCharArray()   | Get-Random -Count 1)
    $chars += ($digits.ToCharArray()  | Get-Random -Count 1)
    $chars += ($special.ToCharArray() | Get-Random -Count 1)

    $all = ($upper + $lower + $digits + $special).ToCharArray()
    for ($i=1; $i -le ($Length - 4); $i++) {
        $chars += ($all | Get-Random)
    }

    return (-join ($chars | Get-Random -Count $chars.Count))
}

function Get-UniqueSamAccountName {
    param([string]$BaseSam)

    if ([string]::IsNullOrWhiteSpace($BaseSam)) { return $null }

    # SamAccountName praktisch max 20 Zeichen
    if ($BaseSam.Length -gt 20) { $BaseSam = $BaseSam.Substring(0,20) }

    $sam = $BaseSam
    $i = 2

    while (Get-ADUser -Filter "SamAccountName -eq '$sam'" -ErrorAction SilentlyContinue) {
        $suffix = "$i"
        $cut = [Math]::Min(20 - $suffix.Length, $BaseSam.Length)
        $sam = $BaseSam.Substring(0, $cut) + $suffix
        $i++
    }

    return $sam
}

# ========== Start ==========
Write-Log "Start: AD User Creation Script"
Write-Log "CSV: $CsvPath"
Write-Log "OU : $OU"

if (-not (Test-Path $CsvPath)) {
    Write-Log "CSV nicht gefunden: $CsvPath" "ERROR"
    throw "CSV nicht gefunden: $CsvPath"
}

$PasswordExport = @()

Import-Csv -Path $CsvPath -Delimiter $CsvDelimiter | ForEach-Object {

    try {
        $Given = $_.GivenName
        $Sur   = $_.Surname

        if ([string]::IsNullOrWhiteSpace($Given) -or [string]::IsNullOrWhiteSpace($Sur)) {
            Write-Log "Übersprungen: GivenName oder Surname fehlt in einer CSV-Zeile." "WARN"
            return
        }

        # Login: vorname.nachname (mit Umlaut-Umschreibung)
        $baseSam = (Normalize-LoginPart $Given) + "." + (Normalize-LoginPart $Sur)
        $baseSam = $baseSam.Trim(".")

        if ([string]::IsNullOrWhiteSpace($baseSam)) {
            Write-Log "Übersprungen: Login konnte nicht generiert werden für '$Given $Sur'." "WARN"
            return
        }

        # Dubletten lösen
        $Sam = Get-UniqueSamAccountName -BaseSam $baseSam
        $Upn = "$Sam@$UpnSuffix"

        # Zufälliges Startpasswort
        $PlainPw  = New-RandomPassword -Length 14
        $PwSecure = ConvertTo-SecureString $PlainPw -AsPlainText -Force

        # Benutzer anlegen
        New-ADUser -Name "$Given $Sur" `
            -GivenName $Given `
            -Surname $Sur `
            -DisplayName "$Given $Sur" `
            -SamAccountName $Sam `
            -UserPrincipalName $Upn `
            -Path $OU `
            -AccountPassword $PwSecure `
            -Enabled $true `
            -ChangePasswordAtLogon $true

        Write-Log "Erstellt: '$Given $Sur' | SAM='$Sam' | UPN='$Upn'"

        # Optional: Passwortliste verschlüsselt speichern
        if ($EnableEncryptedPasswordExport) {
            $PasswordExport += [pscustomobject]@{
                SamAccountName    = $Sam
                UserPrincipalName = $Upn
                GivenName         = $Given
                Surname           = $Sur
                InitialPassword   = (ConvertTo-SecureString $PlainPw -AsPlainText -Force)
            }
        }

    } catch {
        Write-Log "Fehler bei '$($_.GivenName) $($_.Surname)': $($_.Exception.Message)" "ERROR"
    }
}

if ($EnableEncryptedPasswordExport -and $PasswordExport.Count -gt 0) {
    $PasswordExport | Export-Clixml -Path $EncryptedPwFile
    Write-Log "Verschlüsselte Passwortliste gespeichert: $EncryptedPwFile"
}

Write-Log "Ende: Script fertig"
Write-Host "Fertig."
Write-Host "Log: $LogFile"
if ($EnableEncryptedPasswordExport) { Write-Host "Passwortliste (verschlüsselt): $EncryptedPwFile" }

4) Script ausführen

PowerShell als Admin öffnen:

cd C:\Users\bauer.AD\Documents
.\Create-ADUsers.ps1

(oder Script rein kopieren und laufen lassen, wenn du gern gefährlich lebst)


Was du danach bekommst

  • Benutzer sind in rubinhood\Users sichtbar (ADUC / dsa.msc)
  • Log-Datei wie: ADUserCreate_20260114_211026.log
  • optional: InitialPasswords_*.clixml (verschlüsselt, kein Klartext)


Typische Fehler (und schnelle Lösungen)

CSV nicht gefunden

  • Pfad stimmt nicht oder du bist im falschen Ordner → $BaseFolder prüfen

Passwort-Policy

  • Wenn Domain Policy strenger ist, kann selbst “zufällig” zu schwach sein → Passwortregeln anpassen oder Generator erweitern

Umlaute / Sonderzeichen

  • Werden automatisch ersetzt und bereinigt → Login bleibt AD-tauglich

Doppelte Namen

  • Script vergibt automatisch noah.fischer2, noah.fischer3 usw. → Standard in vielen Umgebungen, weil eindeutig und simpel
Sicherheitspatches auf Linux/Windows-Systemen anwenden
Sicherheitspatches auf Linux/Windows-Systemen anwenden
Der Schutz von IT-Systemen vor Angriffen und Schwachstellen ist eine der wichtigsten Aufgaben in der Systemadministration. Eine zentrale ...
vCenter Client installieren
vCenter Client installieren
Diese Anleitung zeigt dir Schritt für Schritt, wie du den vCenter Client mit VMware Workstation installierst. Wenn du die Schritte sorgfä...