Du möchtest Benutzer-Sessions auf einem Windows (Terminal-)Server ohne RDP beenden? Mit PowerShell-Remoting und den Bordmitteln quser/logoff geht das schnell, sicher und reproduzierbar. Unten findest du einen interaktiven Skript-Workflow plus eine schlanke Alternative ganz ohne Remoting.
Enable-PSRemoting in einer administrativen PowerShell).Enable-PSRemoting in Standardkonfiguration).# Alle Sessions auf einem Server anzeigen
quser /server:<Servername>
# Session-ID (Spalte "ID") des Zielusers ablesen und abmelden
logoff <ID> /server:<Servername>
# Interaktives Remote-Abmelden eines Benutzers von einem Windows-/RDS-Server
# Hinweis: Ausführen mit administrativer PowerShell
Write-Host "Bitte geben Sie Anmeldeinformationen ein (Benutzername/Passwort)." -ForegroundColor Cyan
$cred = Get-Credential
Write-Host "Bitte Namen des Zielservers eingeben (z. B. rds01.contoso.local):" -ForegroundColor Cyan
$serverName = Read-Host
Write-Host "Benutzernamen eingeben dessen Session beendet werden soll (z. B. mmustermann):" -ForegroundColor Cyan
$username = Read-Host
try {
# Remoting-Session zum Server aufbauen
$session = New-PSSession -ComputerName $serverName -Credential $cred -ErrorAction Stop
} catch {
Write-Error "Remote-Sitzung konnte nicht aufgebaut werden: $($_.Exception.Message)"
return
}
try {
# Remote: QUSER ausführen, Zeile(n) zum Benutzer finden und Session-ID(s) extrahieren
$scriptBlock = {
param($u)
# QUSER ausführen und Zeilen zum Benutzer filtern (Zeilenanfang mit Username)
$lines = quser | Select-String -Pattern ("^\s*{0}\s+" -f [regex]::Escape($u))
if (-not $lines) {
return @{ Found = $false; Message = "Benutzer nicht gefunden." }
}
# Mehrere Sessions möglich (z. B. mehrere RDP-Sitzungen)
$ids = @()
foreach ($line in $lines) {
# Robust: Spalten via Regex erfassen; ID steht typischerweise in Spalte 3
$m = [regex]::Match($line.Line, '^\s*(\S+)\s+(\S+)?\s+(\d+)\s+')
if ($m.Success) { $ids += $m.Groups[3].Value }
}
if ($ids.Count -eq 0) {
return @{ Found = $false; Message = "Keine Session-ID ermittelbar." }
}
return @{ Found = $true; SessionIds = $ids }
}
$result = Invoke-Command -Session $session -ScriptBlock $scriptBlock -ArgumentList $username
if (-not $result.Found) {
Write-Error $result.Message
Remove-PSSession $session
return
}
# Falls mehrere Sessions: Auswahl anzeigen
$sessionIds = $result.SessionIds
Write-Host "Gefundene Session-ID(s) für Benutzer '$username': $($sessionIds -join ', ')" -ForegroundColor Green
if ($sessionIds.Count -gt 1) {
Write-Host "Mehrere Sitzungen gefunden. Bitte gewünschte ID eingeben:" -ForegroundColor Yellow
$chosenId = Read-Host
if (-not ($sessionIds -contains $chosenId)) {
Write-Error "Ungültige ID-Auswahl."
Remove-PSSession $session
return
}
$targetId = $chosenId
} else {
$targetId = $sessionIds[0]
}
# Remote: Session abmelden
$logoffBlock = {
param($id)
try {
logoff $id
return @{ Ok = $true; Message = "Session $id wurde abgemeldet." }
} catch {
return @{ Ok = $false; Message = $_.Exception.Message }
}
}
$logoffResult = Invoke-Command -Session $session -ScriptBlock $logoffBlock -ArgumentList $targetId
if ($logoffResult.Ok) {
Write-Host $logoffResult.Message -ForegroundColor Green
} else {
Write-Error "Fehler beim Abmelden: $($logoffResult.Message)"
}
}
finally {
# Aufräumen
if ($session) { Remove-PSSession $session }
}
quser liefert tabellarische Ausgabe mit Spalten USERNAME, SESSIONNAME, ID, STATE usw. Die obige Regex ((\d+)) extrahiert die ID robust, auch wenn SESSIONNAME leer ist.Wenn Remoting nicht gewünscht ist, kannst du die Bordmittel direkt vom Admin-PC nutzen:
# Sessions auf dem Remote-Server listen und ID(s) ablesen
quser /server:<Servername>
# Abmelden per ID (<ID> ersetzen)
logoff <ID> /server:<Servername>
Für automatisierte Abläufe lässt sich das mit klassischen Tools (psexec, Aufgabenplanung) kombinieren – Remoting ist aber meist die sauberere Wahl.
H@ppy H@cking