gymedu
Goto Top

Löschen von Userprofilen auf Windows10-Clients unter Windows Server 2019

Hallo zusammen,
mein letzter Hilferuf hatte bereits die Thematik des Löschens von lokal gespeicherten Userprofilen zum Inhalt.
Zunächst habe ich per PS-Script und unter Zuhilfenahme von WinLogOnView alle User in eine Datei geschrieben, die lokal auf den Clients gelöscht werden können. Zunächst habe ich händisch an einem Client - wie
hier beschrieben - Profile gelöscht. Dabei zeigte sich, dass einige Profile über die Systemsteuerung gar nicht gefunden werden, wohl aber der entsprechende Ordner in C:\Users vorhanden ist. Auch dieser lässt sich händisch löschen, obwohl diese Methode nicht empfohlen wird. Die Anmeldung erfolgte auf dem Client per lokalem Administrator oder auch als Domänenadministrator. Damit war zunächst ein - wenn auch sehr umständlicher - Ansatz gegeben. Die erste Frage ist, mit welchen Konsequenzen man rechnen muss, wenn man die Ordner auf C:\Users löscht?
Nach einigen Versuchen bin ich mit 3 verschiedenen Ansätzen per Script vorgegangen um den Vorgang zu automatisieren. Leider scheitere ich stets an folgender o. ä. Fehlermeldung, hier die auf das erste Script:
Remove-CimInstance : Dem Client fehlt ein erforderliches Recht. 
In E:\Test\Delete_CIMInstance_Auswahl.ps1:13 Zeichen:75
+ ... serprofile -Filter "SID = '$($UserAccount.SID)'" | Remove-CimInstance  
+                                                        ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (Win32_UserProfi...5-395216887...):CimInstance) [Remove-CimInstance], CimException
    + FullyQualifiedErrorId : HRESULT 0x80070522,Microsoft.Management.Infrastructure.CimCmdlets.RemoveCimInstanceCommand
Die Scripte sind dabei auf die wesentlichen Zeilen reduziert, alle laufen mit WhatIf oder Weglassen des Löschbefehls und Kontrollausgabe fehlerfrei.
Script 1)
$UserAccount = Get-CimInstance Win32_UserProfile -Filter "Loaded = '$false'" | Ogv -Title 'Wähle den UserAccount den du löschen möchtest!' -PassThru   
# Get-CimInstance Win32_Userprofile -Filter "SID = '$($UserAccount.SID)'" | Remove-CimInstance 

Script 2)

Get-WmiObject -class Win32_UserProfile | 
  Where { ($_.localpath -eq "C:\Users\$irgendeinUser")} | Remove-WmiObject}  

Script 3)

$profiles = Get-WmiObject -Class Win32_UserProfile -ErrorAction SilentlyContinue
foreach ($profile in $profiles) {   
    # Translate User SID to Profilename
    $objSID = New-Object System.Security.Principal.SecurityIdentifier($profile.sid)            
    $objuser = $objsid.Translate([System.Security.Principal.NTAccount])
    $profilename = $objuser.value.split("\")[1]  # Split [1] erzeugt Username  
    # $Deleters ist ein Array, in dem die Usernamen gespeichert sind
    $inDeleters = $false  # Flag um Mitgliedschaft in Deleters festzustellen
    foreach ($del in $deleters) {if ($del -like "$profilename*") {$inDeleters = $true}}  

    if ($inDeleters) { $profile.delete() }
}

Ich hoffe, ich habe die Bedingungen ausreichend genau formuliert. Ich wäre sehr dankbar, wenn mir jemand beim Abstellen des Fehlers helfen könnte, Außerdem würde mich natürlich der worst case interessieren, wenn ich die Methode Nur Löschen der Ordner in C:\Users wählen würde.

Gruß

PS Den Weg über das Löschen von alten Profilen per GPO habe ich registriert, möchte ihn aber erst nach Bereinigung einschlagen.

Content-ID: 1847160278

Url: https://administrator.de/contentid/1847160278

Ausgedruckt am: 19.11.2024 um 09:11 Uhr

gymedu
gymedu 07.02.2022 um 14:07:26 Uhr
Goto Top
Zusatz:
Im ersten Script steckt noch ein kleiner Fehler, da die zweite Zeile auskommentiert ist. Richtig ist:
$UserAccount = Get-CimInstance Win32_UserProfile -Filter "Loaded = '$false'" | Ogv -Title 'Wähle den UserAccount den du löschen möchtest!' -PassThru   
Get-CimInstance Win32_Userprofile -Filter "SID = '$($UserAccount.SID)'" | Remove-CimInstance  
gymedu
gymedu 08.02.2022 um 12:29:26 Uhr
Goto Top
Der Fehler ist einfach zu beheben aber peinlich zuzugeben:
Man muss sich nicht nur als Admin am Client anmelden, sondern auch PowerShell selbst nochmals als Administrator ausführen.
Als PowerShell-Einsteiger lernt man täglich dazu und auch den Funktionsumfang zu schätzen.
Falls es jemand interessiert, wenn das Script fertig ist, werde ich es hier einstellen.
gymedu
Lösung gymedu 16.02.2022 um 20:10:14 Uhr
Goto Top
Nach den ersten erfolgreichen Durchläufen stelle ich hier mein Script ein, vlt. nützt es ja jemand, wenn nicht, kann ich den Thread mit gutem Gewissen auf gelöst setzen. Die Syntax ist sicher noch stark komprimierbar, aber ich bin noch am Anfang meiner PS-Erfahrungen.
<#
.Synopsis
   Greift auf eine Datei C:\Test\Deleters.csv zu, in der alle zu löschenden lokal 
   gespeicherten Userprofile aufgeführt sind und löscht diese mittels CIMInstance
.Description
   Als erste Aktion wird die Datei Deleters eingelesen und von der Kopfzeile und ""   
   befreit in dem String-Array $Deleters gespeichert. Mit Get-CimInstance Win32_UserProfile
   werden dann alle auf dem lokalen Rechner auffindbaren lokalen User unter
   $UserAccounts durchlaufen und überprüft ob sie in $Deleters enthalten sind.
   Falls ja, wird das komplette lokale Profil gelöscht. Außerdem wird bei vollständigem
   Durchlauf der freigegebene Speicherplatz und die Uhrzeit ermittelt. Die Ausgaben in der
   Konsole werden in einer Datei Protokoll_Name des Computers.txt gespeichert. Hierdurch
   können die Protokolle zentral unterschieden werden.
#>

$start = (Get-Date).DateTime
$Protokoll = @()
$FreeSpaces = Get-PSDrive | Where-Object -Property Root -EQ "C:\" | Select-Object -Property Free  
$begin = "{0:n2}" -f($FreeSpaces.Free/1gb)  
Write-Host "Delete running ...  FreeSpace = $begin GB  $start  auf Computer $env:computername"  
$Protokoll += "Delete running ...  FreeSpace =  $begin GB  $start  auf Computer $env:computername"  

$allDeleters = Get-Content -Path "C:\Test\Deleters.csv"  
# Kopfzeile und " entfernen  
$Deleters = @()
ForEach ($dlt in $allDeleters) {
  if (!($dlt -eq "Name")) {$Deleters += $dlt.Replace('"','')}  
}

$DeletersCount = $Deleters.length-1 #Gesamtanzahl zu löschender Profile ohne Header
$DeletersAct = 0                    #Laufende Nr

$UserAccounts = Get-CimInstance Win32_UserProfile -Filter "Loaded = '$false'"  
# Durchlauf über alle gefundenen CIM-Instanzen

ForEach ($User in $UserAccounts) {
  $UserName = $User.LocalPath.remove(0,9)  # C:\Users\Name des Users
  $inDeleters = $false

  # Prüfen ob CIM-Instanz gelöscht werden kann
  ForEach ($del in $Deleters) {
    If ([String] $del -eq $UserName) {$inDeleters = $true}
  } 

  if ($inDeleters) {
    try {
       Get-CimInstance Win32_Userprofile -Filter "SID = '$($User.SID)'" | Remove-CimInstance # -WhatIf  
       $DeletersAct ++
       Write-Host “$DeletersAct / $DeletersCount --> Profil $UserName deleted“
       $Protokoll += “$DeletersAct / $DeletersCount --> Profil $UserName deleted“
    }
    catch {            
         Write-Host "Failed to delete the profile $UserName"  
         $Protokoll += "Failed to delete the profile $UserName"            
      }
  }
  else {
    Write-Host "$UserName not found in Deleters"  
    $Protokoll += "$UserName not found in Deleters"  
  }
}

$FreeSpaces = Get-PSDrive | Where-Object -Property Root -EQ "C:\" | Select-Object -Property Free  
$end = "{0:n2}" -f($FreeSpaces.Free/1gb)  
$stop = (Get-Date).DateTime
Write-Host "Stop running ...  FreeSpace =  $end GB  $stop"  
$Protokoll += "Stop running ...  FreeSpace =  $end GB   $stop"  
$dif = "{0:n2}" -f(($end - $begin)/100)  
Write-Host "Freigegebener Speicherplatz:  $dif  Gb auf Computer $env:computername"  
$Protokoll += "Freigegebener Speicherplatz:  $dif  GB auf Computer $env:computername"  

$Protokoll | Tee-Object "C:\Test\Protokoll_$env:computername.txt"