Skip to the main content.

ScriptRunner Blog

Meine Top 10 PowerShell-Befehle zur Fehlerbehebung bei Windows-Problemen

Inhaltsverzeichnis

Post Featured Image

Lassen Sie mich zunächst ein wenig Hintergrundinformationen über mich erzählen, da dies, so hoffe ich, dazu beitragen wird, diesem Artikel Kontext und Legitimität zu verleihen.

Ich komme aus der Software-Entwicklung und habe meinen ersten Code 1980 geschrieben, aber 1995 kam ich mit den Produkten einer Firma namens Citrix in Berührung, und seitdem löse ich Probleme die mit ihnen, oder genauer gesagt, meistens mit den Anwendungen, die auf ihnen ausgeliefert werden, entstehen.

Früher war dies eine manuelle Angelegenheit, die mühsam, langweilig und fehleranfällig war. Da ich von Natur aus faul bin, habe ich versucht, die Fehlerbehebung zu vereinfachen, zu beschleunigen und zu automatisieren, wo immer dies möglich und praktikabel ist, und zwar mit PowerShell.

Dieser Artikel teilt einen Teil meines Erfolges auf diesem Gebiet und ich hoffe, dass er Sie ermutigt, ein effizienterer Problemlöser zu sein, damit Sie mehr Zeit für spannende Dinge haben (obwohl das für mich persönlich oft noch mehr Fehlersuche oder PowerShell-Entwicklung bedeutet)!

Im Folgenden stelle ich eine Liste der PowerShell-Befehle zur Fehlerbehebung vor, die ich am nützlichsten finde und am häufigsten verwende.

Get-CimInstance

Wmi oder CIM (ausgesprochen „Sie Ai Em“), zu dem die PowerShell-Cmdlets in Version 3.0 umgewandelt wurden, ist eine großartige und dennoch einfache und allgemeine Methode, um Informationen über alle möglichen Dinge von einem oder mehreren Computern zu erhalten.

Sie können z. B. detaillierte Informationen über Prozesse, Dienste, Festplatten, Netzwerke, Speicher, Prozessoren, Akkus usw. abrufen. Darüber hinaus fügen einige Unternehmen, wie z.B. Citrix, ihre eigenen WMI-Provider hinzu, um Zugang zu Informationen zu ermöglichen, für deren Abruf ansonsten eine proprietäre API oder eine ausführbare Datei erforderlich wäre.

Beispielsweise liefert dieser Befehl Betriebssystemdetails sowie Installations- und letzte Boot-Zeiten (Abb. 1):

Get-CimInstance -ClassName win32_operatingsystem -ComputerName grl-dc03,grl-sql01,grl-sql03 | select PSComputerName,caption,version,installdate,LastBootUpTime | Format-Table -AutoSize
Abb. 1: Der Befehl Get-CimInstance liefert als Ausgabe Informationen über Betriebssysteme, die in Tabellenform dargestellt werden

Abb. 1: Der Befehl Get-CimInstance liefert als Ausgabe Informationen über Betriebssysteme, die in Tabellenform dargestellt werden

Viele meiner Consulting-Aufträge umfassen die Zustandsprüfung verschiedener Komponenten. Die Art und Weise, wie ich eine große Menge an Informationen über die zu überprüfenden Desktops und Server sammle, die ich nutzen kann, wenn ich nicht vor Ort bin oder keinen Zugang zu den Kundensystemen habe, besteht darin, ein von mir geschriebenes Skript zu verwenden, das fast fünfzig CIM-Klassen aus einer Liste von Computern abfragt, die auf der Kommandozeile oder per Textdatei angegeben werden. Sie können das Script kostenlos von meinem GitHub-Repository herunterladen.

Das Script schreibt die Ergebnisse in csv-Dateien, sodass Sie Ergebnisse von verschiedenen Rechnern einfach vergleichen können, z.B. um die Konsistenz zu prüfen und Anomalien zu erkennen.

Get-WinEvent

Das Windows-Eventprotokoll kann unglaublich nützliche Informationen enthalten, wenn es darum geht, Probleme wie z.B. eine verlangsamte Anmeldung zu beheben.

Aber die richtige Stelle zu finden, an der man diese Informationen findet, kann sich schwierig gestalten, da es auf neueren Betriebssystemen über 300 verschiedene aktive Eventprotokolle gibt, in denen diese Informationen versteckt sein könnten – nicht nur in den System- oder Anwendungseventprotokollen, wie in den alten Tagen.

Mit PowerShell können wir leicht nach bestimmten Ereignissen suchen, indem wir

  • via ID
  • einem bestimmten Zeitbereich
  • nach einem bestimmten Text oder
  • einer Kombination der oben genannten suchen,

was viel einfacher, schneller und skalierbarer ist als das manuelle Durchforsten der Masse an Events in der Eventanzeige.

Hier ein Beispiel für die Verwendung eines Hash-Tabellen-Arguments, auch als Dictionary bekannt, zum Abrufen von Account-Lockout Events innerhalb der letzten zwölf Stunden von einem remoten Domänencontroller, einschließlich des Computers, von dem die Sperre verursacht wurde (Abbildung 2 und 3):

Get-WinEvent -ComputerName grl-dc03 -FilterHashtable @{LogName = 'Security';Id = 4740;StartTime = (Get-Date).AddHours( -12) } -ErrorAction SilentlyContinue | Select TimeCreated,@{n='User';e={$_.Properties[0].value}},@{n='From';e={$_.Properties[1].Value}}

Der Befehl Get-WinEvent liefert als Ausgabe Informationen über Account-Lockout Events innerhalb der letzten zwölf Stunden von einem remoten Domänencontroller, die in Tabellenform angezeigt werden

Abb. 2: Der Befehl Get-WinEvent liefert als Ausgabe Informationen über Account-Lockout Events innerhalb der letzten zwölf Stunden von einem remoten Domänencontroller, die in Tabellenform angezeigt werden

Screenshot der Windows-Ereigniseigenschaften

Abb. 3: Screenshot der Windows-Ereigniseigenschaften

Beachten Sie im Befehl, wie wir das von Get-WinEvent zurückgegebene Array „Eigenschaften“ verwenden, um bestimmte Felder zu extrahieren, damit wir nicht den vollständigen Text des Ereignisprotokolleintrags parsen müssen (Abbildung 4).

Der im Text beschriebene Get-WinEvent-Befehl wählt nur das erste [0]- und zweite [1]-Feld des EventData-Sets

Abb. 4: Der im Text beschriebene Get-WinEvent-Befehl wählt nur das erste [0]- und zweite [1]-Feld des EventData-Sets

Auch hier gibt es ein Script, das ich fast täglich verwende, um alle Ereignisse aus allen aktivierten Eventprotokollen in einem bestimmten Zeitraum abzurufen, wie z.B. eine Benutzeranmeldung, um nach Hinweisen/Gründen für Fehler oder langsame Leistung zu suchen. Auch dieses Script können Sie von meinem GitHub-Repository herunterladen.

Enter-PSSession

Stellen Sie sich ein Szenario vor, bei dem sich Benutzer auf einem bestimmten Computer über schlechte Leistung beschweren, bei dem Versuch, mit mstsc oder ähnlichem auf diesen Rechner zuzugreifen um den Fehler zu beheben, bleibt jedoch die Anmeldung hängen.

Wäre es nicht schön, eine Methode mit geringem Overhead zur interaktiven oder automatisierten Fehlerbehebung auf diesem Gerät zu haben, wie man es mit Telnet oder ssh auf *nix-Maschinen machen kann (z.B. mit dem großartigen kostenlosen Werkzeug PuTTY)?

Die Eingabe des PowerShell-Befehls Enter-PSSession gibt eine Befehlszeilenschnittstelle auf dem Remote-Computer aus, d.h. sofern PowerShell-Remoting über GPO oder manuell über „winrm quickconfig“ oder Enable-PSRemoting-Force aktiviert ist.

Dies ermöglicht die Fehlersuche und -behebung, wie z.B. die Suche nach den höchsten CPU- oder Speicherverbrauchern via Get-Process (Alias ps) und gegebenenfalls deren Beendigung via Stop-Process (Alias kill).

Test-NetConnection

Wie testen Sie, ob ein bestimmter Webserver betriebsbereit ist und läuft? Ping? Nein! Ping testet lediglich, ob ICMP-Antworten aktiviert sind, und testet indirekt die Namensauflösung, wenn keine IP-Adresse verwendet wird. Es bestätigt jedoch nicht, ob ein Prozess auf einem bestimmten Port auf dem Remote-Rechner lauscht und Firewalls die Verbindung zulassen.

In der Zeit vor PowerShell hätte ich telnet.exe für diesen Port-Test verwenet, aber jetzt stellt PowerShell den Befehl Test-NetConnection (alias tnc) zur Verfügung, der die Überprüfung eines bestimmten Ports auf einem Rechner (und auch das Route tracing) ermöglicht, wie Abbildung 5 zeigt:

Test-NetConnection -ComputerName grl-dc03 -Port 443 -InformationLevel Quiet
Test-NetConnection kann verwendet werden, um Informationen über einen bestimmten Port auf einem Rechner abzufragen.

Abb. 5: Test-NetConnection kann verwendet werden, um Informationen über einen bestimmten Port auf einem Rechner abzufragen.

Da es außerdem ein PowerShell-Objekt oder ein Boolesches Objekt zurückgibt, lässt es sich leicht in Scripte integrieren, ohne die Befehlsausgabe von Befehlen wie ping.exe parsen zu müssen, so wie wir es in den schlechten alten Zeiten tun mussten.

Get-ADUser

Dies ist der Sonderling in dieser Liste, da er nicht standardmäßig verfügbar ist: Man muss dafür das ActiveDirectory PowerShell-Modul installiert haben, obwohl dies sehr einfach über den Befehl „Add-WindowsFeature RSAT-AD-PowerShell“ (elevated ausführen) möglich ist.

Viele Anbieter haben PowerShell-Module, mit denen Sie ihre Technologie anbinden und automatisieren können – ich verwende beispielsweise täglich Module von VMware und Citrix.

Get-ADUser und zugehörige Cmdlets, wie z. B. Get-ADGroupMember, ermöglichen es uns, AD-Informationen zu überprüfen und zu ändern, und sie sind besonders nützlich, um eine große Anzahl von Objekten abzufragen und einen Bericht zu erstellen (siehe Export-CSV später).

Hier ist ein Beispiel für die Zählung, wie viele Konten eine Festplatte auf „H:“ gesetzt haben, die wir benötigen könnten, wenn wir einige Wartungsarbeiten durchführen – wir könnten die Festplatte genauso einfach ändern (Abbildung 6):

Get-ADUser -Filter "HomeDrive -eq 'H:'" | Measure-Object
Mit Get-ADUser lassen sich auf einfache Weise Informationen über Benutzer im Active Directory abrufen

Abb. 6: Mit Get-ADUser lassen sich auf einfache Weise Informationen über Benutzer im Active Directory abrufen

Ich finde es auch sehr nützlich, wenn ich auf Kundensystemen arbeite und sie mir keinen Zugang zu AD-Benutzern und Computern gegeben haben, ich aber Eigenschaften für einen Benutzer überprüfen muss, wie z.B. die Gruppenzugehörigkeit.

Get-Process

Häufig müssen wir überprüfen, ob kritische Prozesse laufen, oder Prozesse untersuchen, die wir nicht erkennen. Task-Manager und SysInternals Process Explorer sind zwar nützliche Tools, aber wir können viele Probleme mit dem Cmdlet Get-Process (Alias ps) überprüfen und beheben.

Hier ist ein Beispiel, das alle Prozesse zeigt, die von Ordnern mit „Citrix“ im Namen ausgeführt werden, sortiert nach aufsteigenden Startzeiten dieses Prozesses, wodurch wir feststellen können, ob der Prozess beim Booten, bei der Benutzeranmeldung usw. gestartet wurde. (Abbildung 7):

Get-process | Where Path -match 'Citrix' | Select Name,Id,StartTime,Path | Sort StartTime | Format-Table -AutoSize
Get-Process kann verwendet werden, um nach Prozessen zu filtern, die „Citrix“ im Namen enthalten, und um spezifische Informationen über sie anzuzeigen.

Abb. 7: Get-Process kann verwendet werden, um nach Prozessen zu filtern, die „Citrix“ im Namen enthalten, und um spezifische Informationen über sie anzuzeigen.

Hier ist ein ähnlicher Befehl: Dieser sucht nach „VMware“ im Firmennamen innerhalb der Versionsressourcen der .exe-Dateien aller laufenden Prozesse (Abbildung 8 und 9):

Get-Process | Get-itemProperty -EA Silent | Select -ExpandProperty VersionInfo | Where CompanyName -match 'VMware' | Select FileVersion,ProductName,FileName
Get-Process kann verwendet werden, um nach Prozessen zu filtern, die "VMware" in ihrem Firmennamen enthalten, und um spezifische Informationen über sie anzuzeigen

Abb. 8: Get-Process kann verwendet werden, um nach Prozessen zu filtern, die "VMware" in ihrem Firmennamen enthalten, und um spezifische Informationen über sie anzuzeigen

Den Firmennamen finden Sie in der Regel in den Eigenschaftsdetails einer .exe-Datei im Eintrag "Copyright"

Abb. 9: Den Firmennamen finden Sie in der Regel in den Eigenschaftsdetails einer .exe-Datei im Eintrag "Copyright"

Get-ChildItem

Es kann gut sein, dass Sie diesen Befehl schon einmal verwendet haben, ohne sich dessen bewusst zu sein, wenn Sie „dir“ in der PowerShell-Konsole verwendet haben, denn dabei handelt es sich um ein Alias für Get-ChildItem.

Wie der Name schon sagt, liefert Get-ChildItem Informationen über die untergeordneten Elemente (und deren Kinder, usw. sofern wir -recurse einsetzen) eines übergeordneten Elements, wobei das übergeordnete Element ein lokaler oder ein Remote-Dateisystemordner, ein Registry-Schlüssel, ein Zertifikatsspeicher usw. sein kann (Tipp: Führen Sie Get-PSDrive aus, um zu sehen, welche PowerShell-Laufwerke verfügbar sind).

Hier ein Beispiel, das Details in einem gegebenen Ordner und in dessen Unterordnern zeigt, einschließlich aller versteckten Elemente, was durch die Angabe von -force ermöglicht wird, für jede Datei mit einer Größe von mehr als 100 MB, sortiert in absteigender Reihenfolge (Abb. 10).

Get-ChildItem -Force -Recurse -File | Where Length -gt 100MB | Sort Length -Descending | Select fullname, CreationTime, @{n='Size (MB)'; e={[math]::Round($_.Length / 1MB , 2)}}}
Abrufen von Details in einem bestimmten Ordner und untergeordneten Elementen mit dem Befehl Get-ChildItem, für jede Datei, die größer als 100 MB ist, sortiert in absteigender Reihenfolge.

Abb. 10: Abrufen von Details in einem bestimmten Ordner und untergeordneten Elementen mit dem Befehl Get-ChildItem, für jede Datei, die größer als 100 MB ist, sortiert in absteigender Reihenfolge.

Get-Help

Dieser Befehl unterscheidet sich insofern etwas von den anderen, die ich bisher vorgestellt habe, als dass es nicht direkt zur Fehlerbehebung beiträgt. Was es uns jedoch bietet, ist eine detaillierte Hilfe bspw. zu Verwendung, Parametern und Beispielen für Cmdlets, die sowohl eingebaute als auch nachträglich installierte Module abdeckt.

Dies, gepaart mit Get-Command, um zu sehen, welche Befehle mit einem bestimmten Modul geliefert werden oder sich auf Netzwerke, Laufwerke usw. beziehen, ermöglicht es, unbekannte Befehle schnell zu verwenden, ohne auf die beliebte Web-Suchmaschine zurückgreifen zu müssen.

Ich benutze es normalerweise mit -ShowWindow, um die Hilfe in einem separaten Textfenster anzuzeigen, außerdem ist -Online nützlich, um zu einer Webseite mit den neuesten Informationen zu gelangen, die manchmal auch zusätzliche Informationen und Links zu verwandten Themen enthält.

Denken Sie daran, dass Sie mit der Tabulatortaste durch die verfügbaren Argumente navigieren oder Strg-Leertaste verwenden können, um sie alle anzuzeigen, und dass Scriptautoren wie ich die erforderlichen Kommentare zu unseren Scripten hinzufügen, damit Get-Help auch mit ihnen funktioniert.

Out-GridView

Mit diesem Cmdlet können von PowerShell-Cmdlets, -Funktionen oder -Skripts ausgegebene Objektdaten einfach in einer Rasteransicht angezeigt werden, die dann sortiert und gefiltert werden kann, ohne dass außer PowerShell (und .NET) weitere Software installiert werden muss.

Ausgewählte Elemente können sogar zur weiteren Verwendung in Scripten zurückgegeben werden, z.B. um ein Element aus einer Liste auszuwählen, oder einfach in die Zwischenablage kopiert werden (über das Argument -passthru).

Hier ist ein Einzeiler, den ich häufig verwende, um die IIS-Protokolldatei des Tages in eine Rasterdarstellung zu bekommen, damit ich nach Fehlern, langsamen Antwortzeiten usw. suchen kann:

Get-Content -Path "C:\inetpub\logs\logfiles\w3svc3\$(Get-Date -Format 'u_exyyMMdd.lo\g')"|Where-Object { $_ -match '^(\d|#Fields)' } | ForEach-Object { $_ -replace '^#Fields: ' } |ConvertFrom-Csv -Delimiter ' '|Where-Object cs-uri-stem -NotMatch 'monitor.aspx$' |Select-Object -Property *,@{name='Duration';expression={([int]$_.'time-taken')}} |Out-GridView
Mit dem Befehl Out-GridView können Sie die Daten, die Sie mit PowerShell abgefragt haben, in einem übersichtlichen Raster formatieren.

Abb. 11: Mit dem Befehl Out-GridView können Sie die Daten, die Sie mit PowerShell abgefragt haben, in einem übersichtlichen Raster formatieren.

Und Abbildung 12 zeigt die eine Zeile, die ich ausgewählt hatte, als ich in der Grid-Ansicht auf die Schaltfläche „OK“ geklickt habe, und die ich mit Set-Clipboard (alias scb) in die Zwischenablage gelegt habe, um sie in meine Notizen zur Fehlerbehebung/Gesundheitsüberprüfung einzufügen (Wie, Sie benutzen immer noch Stift und Papier?!).

Ausgabe des oben beschriebenen Befehls.

Abb. 12: Ausgabe des oben beschriebenen Befehls.

Export-Csv

Zu guter Letzt ist Export-Csv ein integriertes Cmdlet, mit dem wir beliebige PowerShell-Objekte (z. B. die Ausgabe von Cmdlets, die zuvor wie Get-Process dargestellt wurden) in eine korrekt formatierte CSV-Datei schreiben können, um sie in Microsoft Excel, Google Sheets usw. zu untersuchen, filtern, sortieren usw. oder sie sogar über Import-CSV zur weiteren Verarbeitung wieder in PowerShell einzubringen (Abbildung 13).

Exportieren von mit PowerShell abgerufenen Daten in eine .csv-Datei

Abb. 13: Exportieren von mit PowerShell abgerufenen Daten in eine .csv-Datei

Beachten Sie die Verwendung von -NoTypeInformation, die verhindert, dass eine Zeile mit Eigenschaftstypen an die CSV ausgegeben wird, was Excel verwirrt, auch wenn diese leicht gelöscht werden kann. Sie können auch -Append verwenden, um neue Objekte an eine vorhandene CSV-Datei anzuhängen, wobei hier zu beachten gilt, dass die Spalten zwischen alt und neu übereinstimmen sollten.

Ich verwende Export-Csv häufig für „Behelfs-Berichte“, bei denen zeitlich automatisierte PowerShell-Scripte Daten aus verschiedenen Quellen zusammenfassen, aus diesen CSV-Dateien erzeugen und diese per Send-MailMessage (das den Zugriff auf einen SMTP-Mail-Server erfordert) per E-Mail an „interessierte“ Parteien senden.

Eine Sache noch: Wenn Sie sich im niederländischen Sprachraum bewegen, sollten Sie -delimiter ‚;‘ verwenden, da hier Semikolons als Trennzeichen verwendet werden – eine Tatsache, für die ich eine ganze Weile gebraucht, um sie herauszufinden, als ich für eine Firma mit Sitz in den Niederlanden gearbeitet habe!

Fazit

Das war’s fürs Erste, Freunde. Bitte beachten Sie: Es gibt keine Rangfolge in dieser – sehr willkürlichen – Liste, so wie es auch keine Rangfolge der Werkzeuge in der Werkzeugkiste Ihres Handwerkers gibt. Wenn man eine Schraube lösen muss, ist es unwahrscheinlich, dass man einen Hammer als erste Wahl herausziehen wird (es sei denn, man ist Jeremy Clarkson, versteht sich).

Viel Spaß bei der Fehlersuche!

Weiterführende Links

Zusammenhängende Posts

5 min read

Microsoft Exchange mit PowerShell managen

2 min read

VMUG Webcast: VMware Management meistern mit PowerCLI

Über den Autor: