PowerShell 7: Dienste auflisten und filtern — Erklärung und optimierte Skripte
Einleitung
In diesem Beitrag erkläre ich Schritt für Schritt ein kurzes PowerShell-7-Skript, das Dienste auf einem Windows-System auflistet, welche gerade laufen. Ich zeige, was der ursprüngliche Code macht, welche Probleme er hat und liefere mehrere optimierte, sichere und praxisnahe Varianten — inklusive eines robusten Funktions-Skripts, das sich in Windows-Domain-Umgebungen gut einsetzen lässt.
Ursprünglicher Code
$list_all_service = get-service
$list_all_service |
where-object { $_.status -eq ‚Running‘ } |
select-object name, displayname, status |
sort-object name
$list_all_service
Schritt-für-Schritt-Erklärung (einfach verständlich)
1) $list_all_service = get-service
– Get-Service fragt alle Dienste des lokalen Rechners ab und liefert Objekte vom Typ ServiceController.
– Das Ergebnis wird in der Variablen $list_all_service gespeichert.
2) $list_all_service | where-object { $_.status -eq ‚Running‘ } | select-object name, displayname, status | sort-object name
– Der Inhalt der Variablen wird in die Pipeline gegeben.
– Where-Object filtert alle Objekte heraus, deren Property Status den Wert ‚Running‘ hat (also nur laufende Dienste).
– Select-Object reduziert die Ausgabe auf die drei Eigenschaften Name, DisplayName und Status.
– Sort-Object sortiert die Ausgabe nach dem Namen (Name).
3) $list_all_service
– Am Ende wird die Variable erneut ausgegeben — das führt dazu, dass alle Dienste (nicht nur die gefilterten) nochmals unverändert in der Standardansicht angezeigt werden.
Probleme und unerwünschtes Verhalten
– Redundante Ausgabe: Die letzte Zeile ($list_all_service) druckt die vollständige Liste erneut. Vermutlich war das unbeabsichtigt und führt zu Verwirrung.
– Speicher: Falls Sie die vollständige Liste nicht für etwas anderes brauchen, ist das Zwischenspeichern in der Variablen unnötig.
– Lesbarkeit: Der Filter in Where-Object kann kompakter geschrieben werden (PowerShell 7 hat optimierte Syntaxmöglichkeiten).
– Remote-Ausführung: Get-Service unterstützt für moderne, domänenorientierte Admin-Aufgaben nicht immer die beste Remote-Option (besser: Get-CimInstance oder CIM-Session für Remoting und Credentials).
Optimierter Minimal-Code (einzeilig)
Get-Service | Where-Object Status -EQ ‚Running‘ | Select-Object Name, DisplayName, Status | Sort-Object Name
– Kürzere Where-Object-Syntax: Where-Object Status -EQ ‚Running‘ ist performanter und lesbarer in PS7.
– Keine unnötige Zwischenspeicherung.
Robustere Version mit Fehlerbehandlung und Parametern
# Skript: Get-RunningServices.ps1
param(
[string]$ComputerName = ‚localhost‘,
[string]$ExportCsvPath = “
)
try {
# Wenn remote und nicht localhost, Get-CimInstance verwenden (besser für Remoting)
if ($ComputerName -ne ‚localhost‘) {
# Verwende Win32_Service über CIM für Remote-Abfrage
$services = Get-CimInstance -ClassName Win32_Service -ComputerName $ComputerName -ErrorAction Stop |
Where-Object State -EQ ‚Running‘ |
Select-Object @{Name=’Name‘;Expression={$_.Name}}, @{Name=’DisplayName‘;Expression={$_.DisplayName}}, @{Name=’Status‘;Expression={$_.State}} |
Sort-Object Name
}
else {
# Lokale Abfrage mit Get-Service
$services = Get-Service -ErrorAction Stop | Where-Object Status -EQ ‚Running‘ | Select-Object Name, DisplayName, Status | Sort-Object Name
}
# Ausgabe auf Konsole
$services | Format-Table -AutoSize
# Optional: als CSV exportieren
if ($ExportCsvPath) {
$services | Export-Csv -Path $ExportCsvPath -NoTypeInformation -Encoding UTF8
Write-Host „Exportiert: $ExportCsvPath“
}
}
catch {
# Robuste Fehlerbehandlung: detaillierte Meldung und Exit-Code
Write-Error „Fehler beim Abrufen der Dienste auf ‚$ComputerName‘: $_“
exit 1
}
Erklärungen zur robusten Version
– Get-CimInstance vs. Get-Service: Für Remote-Abfragen in Domain-Umgebungen ist Get-CimInstance mit CIM/WinRM stabiler und erlaubt Credentials oder CIM-Sessions. Get-Service kann auf entfernten Systemen Einschränkungen haben.
– ErrorAction Stop: Sorgt dafür, dass fehlerhafte Aufrufe in den catch-Block gehen, statt still zu scheitern.
– Parameter: ComputerName und ExportCsvPath machen das Skript wiederverwendbar.
– Export-Csv: Praktisch, um Ergebnisse zu archivieren oder weiterzuverarbeiten.
Alternative: Funktion mit Credential-Unterstützung
function Get-RunningServices {
param(
[Parameter(Mandatory=$false)]
[string]$ComputerName = ‚localhost‘,
[Parameter(Mandatory=$false)]
[System.Management.Automation.PSCredential]$Credential
)
if ($ComputerName -ne ‚localhost‘ -and $Credential) {
# Beispiel mit New-CimSessionOptions und New-CimSession
$so = New-CimSessionOption -Protocol Wsman
$session = New-CimSession -ComputerName $ComputerName -Credential $Credential -SessionOption $so
try {
$services = Get-CimInstance -CimSession $session -ClassName Win32_Service -Filter „State=’Running'“
return $services | Select-Object @{n=’Name‘;e={$_.Name}}, @{n=’DisplayName‘;e={$_.DisplayName}}, @{n=’Status‘;e={$_.State}} | Sort-Object Name
}
finally {
# Session aufräumen
$session | Remove-CimSession
}
}
else {
return Get-Service | Where-Object Status -EQ ‚Running‘ | Select-Object Name, DisplayName, Status | Sort-Object Name
}
}
Hinweise zur Sicherheit und Berechtigungen
– Für Abfragen von Diensten auf entfernten Rechnern benötigen Sie in der Regel Domänen-Anmeldeinformationen mit passenden Rechten oder ein Konto, das Remote-WMI/CIM abfragen darf.
– Verwenden Sie nach Möglichkeit CIM-Session mit expliziten Credentials statt ungesicherten Klartextübertragungen.
– Testen Sie Skripte zunächst in einer Testumgebung.
Performance-Tipps
– Filtern Sie möglichst früh: Verwenden Sie bei Get-CimInstance bereits einen -Filter (z.B. „State=’Running'“), damit der Server nur relevante Daten sendet.
– Vermeiden Sie unnötige Zwischenspeicherungen großer Listen, wenn Sie nur gefilterte Daten brauchen.
Praxisbeispiele
– Lokale schnelle Ausgabe (Konsole):
Get-Service | Where-Object Status -EQ ‚Running‘ | Select-Object Name, DisplayName, Status | Sort-Object Name
– CSV export für Dokumentation:
Get-Service | Where-Object Status -EQ ‚Running‘ | Select-Object Name, DisplayName, Status | Sort-Object Name | Export-Csv -Path „C:\temp\running-services.csv“ -NoTypeInformation
– Remote (CIM) und nur laufende Dienste abfragen:
Get-CimInstance -ClassName Win32_Service -ComputerName SERVER01 -Filter „State=’Running'“ | Select-Object Name, DisplayName, State
Share this content:
Kommentar abschicken