From 788edaace436f2844f2d2bc4b73f2d33cad6baf9 Mon Sep 17 00:00:00 2001 From: buiaca Date: Tue, 28 Jul 2026 18:05:30 +0200 Subject: [PATCH] refactor(Active_Directory): H_Laufwerk_entfernen.ps1 ueberarbeitet - BUGFIX: ungueltigen kombinierten OU-DN in zwei saubere DNs gespalten - Echter -WhatIf/-Confirm-Support via [CmdletBinding(SupportsShouldProcess)] - Sicherheits-Default: Simulation, scharf nur mit -Force - Effizienter AD-Filter (nur User mit HomeDirectory) - Robustere Fehlerbehandlung (Logpfad, Modul-Import, Zusammenfassung) --- Active_Directory/H_Laufwerk_entfernen.ps1 | 174 ++++++++++++++-------- 1 file changed, 112 insertions(+), 62 deletions(-) diff --git a/Active_Directory/H_Laufwerk_entfernen.ps1 b/Active_Directory/H_Laufwerk_entfernen.ps1 index 7ec78c9..65ebd00 100644 --- a/Active_Directory/H_Laufwerk_entfernen.ps1 +++ b/Active_Directory/H_Laufwerk_entfernen.ps1 @@ -1,120 +1,170 @@ <# .SYNOPSIS - Entfernt das H-Laufwerk (Home-Drive) bei Benutzern in bestimmten OUs - und aktualisiert das Beschreibungsfeld inklusive Logging. + Entfernt das H-Laufwerk (Home-Drive) bei Benutzern in bestimmten OUs + und dokumentiert die Aktion im Beschreibungsfeld inkl. Logging. .DESCRIPTION - Das Skript durchläuft ein Array von OUs, sucht alle aktiven Benutzer, - entfernt die Attribute 'HomeDirectory' und 'HomeDrive' (H:) und - ergänzt das 'Description'-Feld um einen Zeitstempel. + Das Skript durchläuft ein Array von OUs, sucht alle Benutzer, die ein + HomeDirectory (H:) haben, entfernt die Attribute 'HomeDirectory' und + 'HomeDrive' und ergänzt das 'Description'-Feld um einen Zeitstempel. + + SICHERHEIT: + - Standardmäßig läuft das Skript im SIMULATIONSMODUS (es werden nur + Logs geschrieben, nichts im AD verändert). + - Mit -WhatIf wird simuliert (PowerShell-Standardverhalten). + - Mit -Force werden die Änderungen SCHarf in AD geschrieben. + - -Confirm fragt vor jeder einzelnen Änderung nach. + Empfehlung: Immer zuerst mit -WhatIf testen, erst dann mit -Force fahren. +.PARAMETER OUList + Array von Distinguished Names (DN) der OUs, die durchsucht werden. + Jede OU MUSS ein eigenständiger, gültiger DN sein. +.PARAMETER LogPath + Verzeichnis für die Logdateien (Default: C:\Temp\H_Laufwerk\Logs). +.PARAMETER Force + Erzwingt die reale Ausführung (ohne Simulation). Vorsicht! +.EXAMPLE + .\H_Laufwerk_entfernen.ps1 -WhatIf + Simuliert die Entfernung und schreibt nur ins Log. +.EXAMPLE + .\H_Laufwerk_entfernen.ps1 -Force + Führt die Entfernung real im AD aus (Vorsicht!). #> -# --- KONFIGURATION --- -# Hier die OUs eintragen. Am sichersten sind vollständige Distinguished Names (DN). -# Beispiel für Kurznamen/Suchbegriffe siehe Filter unten im Skript. -$OUList = @( - "OU=NNG,OU=Users,OU=N-Tree,DC=n-ad,DC=n-ergie, OU=NSG,OU=Users,OU=N-Tree,DC=n-ad,DC=n-ergie" +[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] +param ( + [string[]]$OUList = @( + "OU=NNG,OU=Users,OU=N-Tree,DC=n-ad,DC=n-ergie", + "OU=NSG,OU=Users,OU=N-Tree,DC=n-ad,DC=n-ergie" + ), + [string]$LogPath = "C:\Temp\H_Laufwerk\Logs", + [switch]$Force ) -# Pfad für das Logfile -$LogPath = "C:\Temp\H_Laufwerk\Logs" -$LogFile = Join-Path $LogPath "H-Laufwerk_Entfernung_$(Get-Date -Format 'yyyy-MM-dd').log" - -# SICHERHEITS-SCHALTER (Safety First) -# $true = Es wird nur simuliert und geloggt, was passieren WÜRDE. -# $false = Die Änderungen werden direkt ins Active Directory geschrieben! -$WhatIfMode = $true +# --- SICHERHEIT: Simulation, solange weder -Force noch explizites -WhatIf --- +$Simulate = -not $Force +if ($WhatIfPreference) { $Simulate = $true } # --- FUNKTIONEN --- -Function Write-Log { - Param ( +function Write-Log { + [CmdletBinding()] + param( + [Parameter(Mandatory)] [string]$Message, [ValidateSet("INFO", "SUCCESS", "WARNING", "ERROR")] [string]$Type = "INFO" ) $TimeStamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" - $LogLine = "[$TimeStamp] [$Type] $Message" - - # Konsole-Ausgabe (farblich angepasst) + $LogLine = "[$TimeStamp] [$Type] $Message" + switch ($Type) { "SUCCESS" { Write-Host $LogLine -ForegroundColor Green } "WARNING" { Write-Host $LogLine -ForegroundColor Yellow } "ERROR" { Write-Host $LogLine -ForegroundColor Red } default { Write-Host $LogLine -ForegroundColor Cyan } } - - # In Datei schreiben - $LogLine | Out-File -FilePath $LogFile -Append -Encoding utf8 + + try { + $LogLine | Out-File -FilePath $script:LogFile -Append -Encoding utf8 + } + catch { + Write-Warning "Logdatei konnte nicht geschrieben werden: $_" + } } # --- INITIALISIERUNG --- -if (-not (Test-Path $LogPath)) { - New-Item -ItemType Directory -Path $LogPath -Force | Out-Null +try { + if (-not (Test-Path $LogPath)) { + New-Item -ItemType Directory -Path $LogPath -Force | Out-Null + } +} +catch { + Write-Error "Logverzeichnis konnte nicht erstellt werden: $_" + exit 1 } -Write-Log "=== Skriptstart (WhatIf-Modus = $WhatIfMode) ===" "INFO" +$LogFile = Join-Path $LogPath "H-Laufwerk_Entfernung_$(Get-Date -Format 'yyyy-MM-dd').log" + +Write-Log "=== Skriptstart (Modus: $(if ($Simulate) { 'SIMULATION/WhatIf' } else { 'SCHARF' })) ===" "INFO" # AD-Modul prüfen if (-not (Get-Module -ListAvailable -Name ActiveDirectory)) { Write-Log "Das ActiveDirectory-Modul ist nicht installiert!" "ERROR" - Exit + exit 1 +} +try { + Import-Module ActiveDirectory -ErrorAction Stop +} +catch { + Write-Log "ActiveDirectory-Modul konnte nicht geladen werden: $_" "ERROR" + exit 1 } -Import-Module ActiveDirectory -# Das aktuelle Datum für die Beschreibung generieren $CurrentDate = Get-Date -Format "dd.MM.yyyy" -$AppendText = "H Laufwerk wurde entfernt Datum $CurrentDate" +$AppendText = "H Laufwerk wurde entfernt Datum $CurrentDate" + +$Processed = 0 +$Skipped = 0 +$Failed = 0 # --- HAUPTTEIL --- foreach ($OU in $OUList) { Write-Log "Verarbeite OU: $OU" "INFO" - + try { - # Alle Benutzer aus der aktuellen OU abrufen, die ein HomeDirectory gesetzt haben - $Users = Get-ADUser -SearchBase $OU -SearchScope Subtree -Filter * -Properties Description, HomeDirectory, HomeDrive + # Nur Benutzer mit gesetztem HomeDirectory laden (effizienter Filter) + $Users = Get-ADUser -SearchBase $OU -SearchScope Subtree ` + -Filter { HomeDirectory -like "*" } ` + -Properties Description, HomeDirectory, HomeDrive -ErrorAction Stop } catch { Write-Log "Fehler beim Lesen der OU '$OU': $_" "ERROR" + $Failed++ continue } - - if ($null -eq $Users -or $Users.Count -eq 0) { - Write-Log "Keine Benutzer in der OU '$OU' gefunden." "WARNING" + + if ($null -eq $Users) { + Write-Log "Keine Benutzer mit H-Laufwerk in der OU '$OU' gefunden." "WARNING" continue } - + + # Bei genau einem Treffer liefert Get-ADUser ein Skalar -> in Array wandeln + if ($Users -isnot [System.Array]) { $Users = @($Users) } + foreach ($User in $Users) { - # Prüfen, ob überhaupt ein H-Laufwerk oder HomeDirectory vorhanden ist - if ([string]::IsNullOrEmpty($User.HomeDirectory) -and [string]::IsNullOrEmpty($User.HomeDrive)) { - Write-Log "Benutzer $($User.SamAccountName): Kein H-Laufwerk konfiguriert. Überspringe." "INFO" - continue - } - - # Neue Beschreibung zusammensetzen (bestehende Beschreibung beibehalten) + # Neue Beschreibung: bestehende Beschreibung beibehalten + Anhang $NewDescription = if ([string]::IsNullOrEmpty($User.Description)) { $AppendText - } else { + } + else { "$($User.Description) | $AppendText" } - - # Log-Eintrag für die Aktion vorbereiten + $ActionMsg = "Benutzer $($User.SamAccountName) - Entferne Pfad: '$($User.HomeDirectory)' ($($User.HomeDrive)) | Neue Beschreibung: '$NewDescription'" - + + if ($Simulate) { + Write-Log "[SIMULATION] $ActionMsg" "INFO" + $Processed++ + continue + } + + if (-not $PSCmdlet.ShouldProcess( + $User.SamAccountName, + "HomeDirectory/HomeDrive entfernen + Beschreibung aktualisieren")) { + $Skipped++ + continue + } + try { - if ($WhatIfMode) { - Write-Log "[WHAT-IF] $ActionMsg" "INFO" - } else { - # Änderungen scharf durchführen - Set-ADUser -Identity $User.SamAccountName ` - -Clear "HomeDirectory", "HomeDrive" ` - -Description $NewDescription - - Write-Log "Erfolgreich angepasst: $($User.SamAccountName)" "SUCCESS" - } + Set-ADUser -Identity $User.SamAccountName ` + -Clear "HomeDirectory", "HomeDrive" ` + -Description $NewDescription + Write-Log "Erfolgreich angepasst: $($User.SamAccountName)" "SUCCESS" + $Processed++ } catch { Write-Log "Fehler beim Verarbeiten von $($User.SamAccountName): $_" "ERROR" + $Failed++ } } } -Write-Log "=== Skript beendet ===" "INFO" \ No newline at end of file +Write-Log "=== Skript beendet | Verarbeitet: $Processed | Übersprungen: $Skipped | Fehler: $Failed ===" "INFO"