Event Viewer durch PowerShell ersetzen – Get-Eventlog / Get-WinEvent

Sicher haben Sie sich auch schon häufiger über den Windows Event Viewer ärgern müssen. Nicht nur, dass dieser bei großen Datenmengen extrem langsam wird, auch die Filtermöglichkeiten sind doch sehr begrenzt. Wenn sich dies auch ab Windows 2008 schon merklich gebessert hat.

Eine echte Alternative ist da die Logauswertung über die PowerShell. Achten Sie bitte darauf, die Powershell als Administrator zu starten, da Sie sonst nicht den vollen Zugriff auf alle EventLogs haben.

Es gibt mehrere Weg zum Ziel, auf die ich im Folgenden näher eingehe. Achten Sie auch immer darauf, dass Events im Log mittlerweile mit dem UTC Zeitstempel erstellt werden. Wenn ich nun Events von einem Remote System auswerte, werden diese automatisch mit ihrem Zeitstempel der Zeitzone des abrufenden System angepasst.

Get-EventLog

Sie können mit dem cmdLet get-eventlog granular filtern. Auch der Remoteabruf eines Logs ist ohne weiteres möglich. Im Folgenden sehen Sie einige Beispiele, denen aber keine Grenzen gesetzt sind.

Beispiel 1:

Wurde ein Server in den letzten 30 Tagen gebootet? Dazu brauchen Sie die EventID 6005 aus dem System EventLog, die vermeldet, dass das EventLog gestartet wurde. Dies geschieht immer nach einem Reboot.

get-eventlog -Computername "Server" -logname system -entrytype information -after (get-date).adddays(-30) |? {$_.EventID -eq 6005} |fl Timegenerated

Zurück geliefert wird das Datum und die Uhrzeit des Eintrags.

Beispiel 2:

Sie möchten wissen, wann zuletzt die Systemzeit eines Remote Servers synchronisiert wurde. Suchen Sie dazu nach der EventID 35 im SystemLog

get-eventlog -Computername "Server" -LogName system -EntryType information -after (get-date).adddays(-100) |? {$_.eventid -eq 35} | fl timeg*,mess*,eve*

Beispiel 3:

Sie rufen alle Error Meldungen des Application Logs der letzten 30 Tage ab

get-eventlog -Computername "Server" -logname application -entrytype error -after (get-date).adddays(-30)

Damit erhalten Sie natürlich eine Vielzahl von Meldungen, die Sie gar nicht interessieren. Angenommen, eine remote Maschine verursacht auf einem DC diverse Fehler, die Sie aber in Ihrer Auswertung ignorieren möchten, dann erreichen Sie das mit folgendem Ausschluss auf dem DC:

get-eventlog -Computername "DCName" -logname application -entrytype error -after (get-date).adddays(-30) |? {$_.message -notlike "Servername"}

Kosmetik:

Wenn Sie sich das ganze noch als GridView ausgeben lassen und somit auch in der Lage sind, graphisch zu filtern, können Sie den Event Viewer gänzlich vergessen.

get-eventlog -logname application -entrytype information -after (get-date).adddays(-30) |out-gridview

eventviewer

Get-WinEvent

Mit Get-WinEvent können Sie noch weit aus mehr Optionen nutzen. Mit dem Parameter –ComputerName ist der Abruf auch remote möglich. Ein großer Vorteil ist, dass Sie gleichzeitig mehrere Logs durchsuchen können, was so einfach mit Get-EventLog nicht möglich ist. Die Abfrage über Get-WinEvent ist zudem wesentlich schneller als Get-EventLog. Sie erreichen auch die Windows Logs über dieses CMDLet.

1

Zusätzlich lässt sich mit diesem CMDLet auch ein archiviertes Log auswerten. Dazu dient der Parameter –Path unter dem Sie dann den Dateinamen des gespeicherten Logs angeben.

Sie haben mit Get-WinEvent im Prinzip keine wirklichen Grenzen mehr bei einer Log Auswertung oder der Suche nach bestimmten Events. Ich gehe hier mal auf zwei Filtermöglichkeiten näher ein. Ja, es gibt noch viel mehr Optionen, aber für mich haben sich die beiden Filter über –FilterHashtable und –FilterXML als die nützlichsten im täglichen Arbeiten heraus kristallisiert.

Für die schnelle Suche: FilterHashtable

Über die Hashtable Option können sie gängige Filter angeben. Diese Option ist nach meinem Geschmack die etwas einfachere und deshalb auch für die schnelle Suche etwas besser geeignet. Wenn Sie z.B. den letzten “unexpected shutdown” suchen, erreichen Sie dies über die Suche der vorher definierten Hashtable, in der Sie das Log und die EventID festlegen.

$Hashtable = @{logname="System";ID="6008"}
 get-winevent -FilterHashtable $Hashtable -MaxEvents 1

Natürlich funktioniert der gleiche Aufruf auch für eine Remote Maschine. So können Sie relativ fix den letzten “unexpected shutdown” einer Liste von Computern erfassen.

$Computer = "Server1","Server2","Server3"
 $Hashtable = @{logname="System";ID="6008"}
 $Computer | % {Get-WinEvent -ComputerName $_ -FilterHashtable $Hashtable -MaxEvents 1}

Noch komfortabler: FilterXML

Über die XML Filteroption können Sie die Suche noch weiter granulieren. Ein einfacher XML Filter (alle kritischen Events aus dem SystemLog) sieht folgendermaßen aus:

$FilterXml = ‘<QueryList>
                                   <Query>
                                             <Select Path=”System”>*[System[(Level=1 )]]</Select>
                                   </Query>
                           </QueryList>’

Der Aufruf erfolgt dann mit:

Get-WinEvent -FilterXml $FilterXml

Über “Level” wählen Sie aus, welche Events Sie erhalten möchten:

Level 1 = Critical
Level 2 = Error
Level 3 = Warning
Level 4 = Information

Einen Einblick über die Möglichkeiten macht die folgende Suchdefinition deutlich:

 $FilterXml = '<QueryList>
                   <Query>
                       <Select Path="Application">*[System[(Level=1 or Level=2 or Level=3) and TimeCreated[timediff(@SystemTime) &lt;= 3600000]]]</Select>
                       <Select Path="System">*[System[(Level=2) and TimeCreated[timediff(@SystemTime) &lt;= 3600000]]]</Select>
                       <Select Path="HardwareEvents">*[System[(Level=4) and TimeCreated[timediff(@SystemTime) &lt;= 7200000]]]</Select>
                   </Query>
               </QueryList>'

Im Application Log werden alle Critical, Error und Warning Events aus der letzten Stunde gesucht. Im Sytem Log werden alle Error Events aus der letzten Stunde gesucht und im HardwareEvents Log werden alle Information Events der letzten 2 Stunden gesucht.

Wie Sie sehen, sind die Möglichkeiten sehr vielfältig. Wildcards können leider nicht genutzt werden, das liegt aber im XML Format begründet.

Und hier noch einige Beispiele:

Beispiel 1:

Sie möchten die letzten 50 Events aus den Logs Application und System sehen.

Get-WinEvent -LogName appl*,sys* -MaxEvents 50

Beispiel 2:

Sie möchten alle Fehler der letzten 24 Stunden im System Log sehen.

Get-WinEvent -FilterHashtable @{logname="system";level=2;starttime=(get-date).addhours(-24)}

Beispiel 3:

Sie möchten aus dem Windows Log Microsoft-Windows-Kernel-EventTracing/Admin alle Events mit dem Opcode 14 sehen. Achten Sie darauf, dass die Abfrage des XML Pfades Case Sensitive ist!

Get-WinEvent -LogName "Microsoft-Windows-Kernel-EventTracing/Admin" -FilterXPath "*/System[Opcode=14]"

Beispiel 4:

Sie möchten sehen, ob das letzte Windows Backup auf einer Remote Maschine erfolgreich durchgelaufen ist.

Get-WinEvent -ComputerName Computername -FilterHashtable @{logname="Microsoft-Windows-Backup";Id=14} -MaxEvents 1

Beispiel 5:

Zum Abschluss noch eine Suche, die sehr deutlich macht, dass in Flexibilität und Geschwindigkeit der Event Viewer auch nicht ansatzweise mithalten kann.

Zuerst lesen wir alle verfügbaren Logs mit Einträgen in eine Variable.

$Logs = Get-WinEvent -ListLog * |? {$_.RecordCount -gt 0}

Damit sind auch alle Windows- und Anwendungslogs enthalten.

Nun möchten Sie in einem bestimmten Zeitfenster nach Fehlern und Warnungen suchen. Sagen wir zwischen 13:00 Uhr und 13:45 Uhr

$Start = Get-Date "13:00"
$End = Get-Date "13:45"

$Logs | % {Get-WinEvent -ea si -FilterHashtable @{logname=$_.logname;starttime=$start;
endtime=$end;level=2,3}}

Testen Sie das Beispiel. Sie werden absolut überrascht sein, wie schnell das Ergebnis erscheint.