PowerShell Beispiele: Eventlog
Was für den UNIX-Administrator seine Syslogs sind, ist bei Windows das Eventlog. Aus Sicht eines PowerShell Entwicklers gibt es da zwei Aspekte:
- Eventlogs lesen und auswerten
- SelbstEvents schreiben
Diese Themen wird auf dieser Seite behandelt
Eventlogs lesen
Über das Commandlet "Get-Eventlog" kann man natürlich sehr einfach die Daten der verschiedenen Eventlogs von Windows extrahieren. Seit PowerShell 2 und Windows Vista und höher gibt es mit "Get-WinEvent" eine noch leistungsfähigere Version.
- Get-EventLog
https://technet.microsoft.com/de-de/library/hh849834.aspx - Get-WinEvent
https://technet.microsoft.com/de-de/library/hh849682.aspx - Processing Eventlogs in PowerShell
http://blogs.msdn.com/b/PowerShell/archive/2009/05/21/processing-event-logs-in-PowerShell.aspx
Der größte Vorteil ist dabei die Möglichkeit, alternative Credentials mitzugeben, was speziell bei der Suche auf anderen Computern hilfreich sein kann.
Get-WinEvent vs. Get-Eventlog
Wer nun genau aufgepasst hat, hat zwei Commandlets entdeckt, die eigentlich den gleichen Zweck haben:
CMDlet | Get-WMI | Get-Eventlog | Get-WinEvent |
---|---|---|---|
PowerShell version |
2.0-5.2 nicht PSCore (6.x/7.x) |
2.0-5.2 nicht PSCore (6.x/7.x) |
2.0-5.2 |
Remote | Ja |
Parameter - Computername |
Parameter "-computer" |
Filter | Flexibel oder nachverarbeiten über Pipeline |
Einfache Syntax per Parameter |
FilterXPath auch Remote, was schneller über WAN ist. |
Performance | Schnell |
Langsamer |
Schnell |
So erhalten Sie von allen Exchange Servern in ihrer Topologie alle entsprechenden Events. Sie können natürlich mit Get-WinEvent noch weiter filtern (z.B. Start/Endezeit) und die Ausgaben weiter verarbeiten.
- PowerShell: Get-WinEvent vs.
Get-EventLog
http://www.mcbsys.com/techblog/2011/04/PowerShell-get-winevent-vs-get-eventlog/ - Monitoring Event Logs with
PowerShell
https://blog.netwrix.com/2015/04/06/monitoring-event-logs-with-powershell/ - Advanced Event Log Filtering Using PowerShell
https://blog.netwrix.com/2015/04/29/advanced-event-log-filtering-using-powershell/ - Differences between Windows
PowerShell 5.1 and PowerShell
7.x
https://learn.microsoft.com/en-us/powershell/scripting/whats-new/differences-from-windows-powershell?view=powershell-7.4&source=recommendations#-eventlog-cmdlets
Eventlog und Windows
2008/Vista
Das Script funktioniert leider nicht auf Windows
2008 oder Vista sondern nur auf Windows 2008R2
oder Windows 7, da ein "Bug" in GET-WinEvent den
Einsatz des Filters mit "FilterHashtable" nicht
zulässt und ich aus Gründen der Lesbarkeit nicht
den Filter als XML-Struktur verwenden wollte.
Siehe auch
https://connect.microsoft.com/PowerShell/feedback/details/422072/get-winevent-on-vista-does-not-with-vista-x64-using-ctp3
WMI: Events suchen und filtern
Natürlich ist die Abfrage auch per WMI möglich. Hier ein Beispiel. Hier suche ich 1221 Events der letzten 14 Tage. (Ergebnisse der Online Defragmentierung von Exchange:
$WMIDATEAGE = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime([DateTime]::UtcNow.AddDays(-14)) Get-WmiObject -computer SRV01 ´ -query ("Select * from Win32_NTLogEvent Where Logfile='Application' and Eventcode = '1221' and TimeWritten >='" + $WMIDATEAGE + "'") | foreach-object{ write-host $_.message }
Aber man muss sich gar nicht auf die Tiefen von WMI begeben.
Get-Eventlog: Events suchen und filtern
Das komplette Lesen eines Eventlogs dauert lange und über WAN ist Bandbreite auch kostbar. Daher ist ein normales "Lesen" mit einer nachfolgenden Filterung in der folgenden Form unsinnig:
Get-EventLog -LogName security ` | where {$_.InstanceId -eq }4770
Hierbei würde das Commandlet alle Security Events auslesen und erst dann lokal filtern. Besser ist es hier natürlich schon bei der Anfrage den Filter mit zu geben, so dass der Server selbst schon filtern kann.
Get-EventLog ` -LogName security ` -InstanceId 4770
Sie können die Ergebnisse vorab auch noch weiter einschränken, z.B.: über die Zeit (-Before und -After), Source und EntryType
Mit dem PowerShell Commandlets "Get-Eventlog" bzw. "Get-WinEvent" lässt sich jedes Eventlog einfach auslesen. Denken Sie aber daran, auch hier mit Filtern zu arbeiten.
- Use PowerShell Cmdlet to
Filter Event Log für Easy Parsing
http://blogs.technet.com/b/heyscriptingguy/archive/2011/01/24/use-PowerShell-cmdlet-to-filter-event-log-for-easy-parsing.aspx
Für dein Einsatz unter PRTG wollte ich einfach die Anzahl der "Error-Messages" in den letzten X Minuten haben. Hier am Beispiel eines FIM-Servers, wie er bei Office 365 zum Einsatz kommt.
Get-EventLog ` -LogName application ` -After (get-date).addminutes(-15) ` -EntryType error ` -Source "directory synchronization"
Aber schon beim Test habe ich gesehen, dass die Ergebnisse sehr schnell kommen aber dann lange "Pause" ist. Das liegt wohl daran, dass "Get-Eventlog" auch mit der Angabe eines Filters und selbst bei Angabe von "After" dennoch das komplette Eventlog absucht. Besser ist das mit WMI bzw. Get-WinEvent
$starttime = (get-date).AddMinutes(-15)
$count=(get-winevent -FilterHashTable @{LogName='Application'; Level=3; StartTime=$starttime} ` -ErrorAction silentlycontinue).count
Hierbei werden sehr viel schneller die Meldungen zurück gegeben und können auch noch umfangreicher gefiltert werden. Sogar Platzhalter wie "*" funktionieren. Die ErrorAction muss dazu, da Get-WinEvent ansonsten einen sichtbaren Fehler "Get-WinEvent : No events were found that match the specified selection criteria" erzeugt. Die Level haben folgende Bedeutung:
Level 2 = Error Level 3 = Warning Level 4 = Information
- PowerTip: Find PowerShell
Events and Levels
http://blogs.technet.com/b/heyscriptingguy/archive/2013/08/25/powertip-find-PowerShell-events-and-levels.aspx - Why does get-eventlog -after
take so long to complete?
http://social.technet.microsoft.com/Forums/windowsserver/en-US/b9e902f5-c899-4f97-bca1-a5794464f978/why-does-geteventlog-after-take-so-long-to-complete
Suchen mit WinEvent
Das Commandlet Get-WinEvent ist meiner Erfahrung nach noch etwas schneller und über die XPATH-Syntax leistungsfähiger.
#Sample Suche nach Fehlern Get-WinEvent -FilterHashtable @{logname="Security";level=3;StartTime="01.07.2016";Endtime="11/08/2017" } #Example Suche nach 9646 Events get-winevent ` -FilterHashTable @{LogName = "Application"; ID = 9646; Providername="MSExchangeIS"}} ` -ComputerName $server
Natürlich kann man auch mehrere Server parallel abfragen, z.B. so:
# Einlesen der Servernamen aus einer Datei. Koennte auch eine AD-Abfrage u.a. sein $serverlist = gc .\server.txt # Serverliste an Invoke-Command uebergeben $serverliste ` | %{` Invoke-Command ` -ComputerName $_ ` -Command {get-winevent -FilterHashTable @{LogName = "System"; ID = 41; Providername="Microsoft-Windows-Kernel-Power";StartTime="11/07/2017";Endtime="11/08/2017"}} ` -asjob } # Auf den Abschluss aller Jobs warten Get-job | wait-job # Ergebnisse einsammeln $result=get-job | Receive-Job # Jobs bereinigen get-job | remove-job # Ergebnisse sortiert ausgeben $result | sort TimeCreated| ft PSComputername,timecreated -autosize PSComputerName TimeCreated -------------- ----------- DC2012.msxfaq.net 10/3/2016 5:55:08 PM EX2016.msxfaq.net 10/3/2016 5:57:09 PM SfB2015.msxfaq.net 10/3/2016 6:25:39 PM
Solche Schleifen sind auch sehr effektiv, um über mehrere Server bestimmte Events zu ermitteln, z.B. Datenbank-Failover bei Exchange oder SQL oder Skype for Business Fabric Fehler. Man bekommt dann die Events aller Server zeitlich in einer Liste.
- Get-WinEvent
http://technet.microsoft.com/en-us/library/hh849682.aspx - Speeding up Get-WinEvent in
PowerShell by using
FilterHashTable
http://theboywonder.co.uk/2012/03/15/speeding-up-get-winevent-in-PowerShell-by-using-filterhashtable/ - Examine Your Logs with the
Get-WinEvent Cmdlet
http://www.computerperformance.co.uk/PowerShell/PowerShell_get_winevent.htm - Use FilterHashTable to Filter Event Log
with PowerShell
https://blogs.technet.microsoft.com/heyscriptingguy/2014/06/03/use-filterhashtable-to-filter-event-log-with-powershell/ - User PowerShell CMDLet to filter
eventlog for easy parsing
https://blogs.technet.microsoft.com/heyscriptingguy/2011/01/24/use-powershell-cmdlet-to-filter-event-log-for-easy-parsing/ - Monitoring Event Logs with PowerShell
https://blog.netwrix.com/2015/04/06/monitoring-event-logs-with-powershell/ - Advanced Event Log Filtering Using PowerShell
https://blog.netwrix.com/2015/04/29/advanced-event-log-filtering-using-powershell/
Eventlogs schreiben (NET)
In PowerShell 2.0 ganz es noch kein eigenes Commandlet aber mittelt .NET-Klassen war es schon da nicht schwer einen Eventlogeintrage zu erzeugen:
# Initialize Eventlog für reporting and Debugging $evt=new-object System.Diagnostics.EventLog("Application") $evt.Source="MSXFAQ" $infoevent=[System.Diagnostics.EventLogEntryType]::Information $warnevent=[System.Diagnostics.EventLogEntryType]::Warning $errorevent=[System.Diagnostics.EventLogEntryType]::Error $evt.WriteEntry("SKRIPT gestartet",$infoevent,0)
Dieser Codeschnipsel legt im Application-Log eine neue Quelle "MSXFAQ" an, damit ich im letzten Schritt dann einen Eintrag anlegen kann.
Mit New-Eventlog und "Write-Eventlog", welches aber eine "Source" benötigt, die zuerst zu definieren ist, geht das "lesbarer" aber nicht wirklich kürzer. Da ein "New-Eventlog" aber administrative Rechte braucht, muss man das Skript einmalig als Admin starten oder die Zeile von Hand ausführen. Damit ich später im Skript keine Fehler bekomme, habe ich daher das New-Eventlog in eine IF-Anfrage eingebaut.
# Source bei Bedarf definieren if (![System.Diagnostics.EventLog]::SourceExists("msxfaq")) { new-eventlog -logname 'Application' -Source 'msxfaq' } # Eventlogeintrag erzeugen write-eventlog ` -entrytype "Information" ` -logname "Application" ` -eventID 1 ` -Source 'msxfaq' ` -Category 0 ` -Message "Meldung"
Neben der EventID und dem EntryType können Sie auch noch eine Category übergeben. Folgende Werte sind möglich:
Wert | Bedeutung | Wert | Bedeutung |
---|---|---|---|
0 |
None |
8 |
Undefiniert wird als (8) angezeigt |
1 |
Devices |
9 |
Undefiniert wird als (9) angezeigt |
2 |
Disk |
10 |
Undefiniert wird als (10) angezeigt |
3 |
Printers |
11 |
Undefiniert wird als (11) angezeigt |
4 |
Services |
12 |
Undefiniert wird als (12) angezeigt |
5 |
Shell |
13 |
Undefiniert wird als (13) angezeigt |
6 |
System Event |
14 |
Undefiniert wird als (14) angezeigt |
7 |
Network |
15 |
Undefiniert wird als (15) angezeigt |
Wer also heute ein PowerShell-Skript schreibt und die Ausgabe von Fehlern oder Status als Eventlog vergisst, sollte sich mal fragen wie er all die schönen Skripte überwachen möchte wenn diese später automatisch laufen.
- How to Use PowerShell to Write to Event Logs
https://blogs.technet.microsoft.com/heyscriptingguy/2013/06/20/how-to-use-powershell-to-write-to-event-logs/ - Creating Your Own Eventlog
http://PowerShell.com/cs/blogs/tips/archive/2009/09/29/creating-your-own-eventlog.aspx - How to: Determine If an Event Source Exists
http://msdn.microsoft.com/en-us/library/9t766zhb.aspx - What Can I Do With Windows PowerShell?
http://www.microsoft.com/technet/scriptcenter/topics/msh/cmdlets/get-eventlog.mspx - PowerShell Team Blog - Monitor the Event Log
http://blogs.msdn.com/PowerShell/archive/2006/04/25/583266.aspx - Hey, PowerShell Guy ! How Can I Monitor Event Log Messages für Specific Words?
http://thePowerShellguy.com/blogs/posh/archive/2007/02/26/hey-PowerShell-guy-how-can-i-monitor-event-log-messages-for-specific-words.aspx - Windows Event Log in
PowerShell – Part II (MSDN)
http://blogs.msdn.com/b/PowerShell/archive/2009/06/11/windows-event-log-in-PowerShell-part-ii.aspx - Chapter 23. Event Logs
http://www.pavleck.net/PowerShell-cookbook/ch23.html
Wer statt eines Eventlogs die Meldungen an einen Syslog Server senden will, findet auf Syslog entsprechende Informationen.
Auf Events warten
Interessant ist aber auch die Funktion, einfach auf Events zu warten und die dann automatisch zu verarbeiten. Auch wenn dies mit PowerShell 2.0 noch einfacher geht (Register-WMIEvent auf http://www.microsoft.com/technet/scriptcenter/topics/winpsh/events.mspx), ist auch PowerShell 1.0 schon sehr einfach dazu zu verwenden. Hier ein Beispiel:
$eventwatcher = new-object system.management.ManagementEventWatcher $eventwatcher.query = "Select * From __InstanceCreationEvent Where TargetInstance ISA 'Win32_NTLogEvent'" $event = $eventwatcher.WaitForNextEvent() $event.targetinstance
Das Skript in einer PowerShell-Box gestartet, liefert den nächsten Event, der ein einem beliebigen Eventlog des lokalen Servers auftritt.
Mit so wenig Code kann man natürlich schöne weitere Funktionen bauen.
- TrackLoginEvents
- Use PowerShell to Find the Location of a Locked-Out User
https://blogs.technet.microsoft.com/heyscriptingguy/2012/12/27/use-powershell-to-find-the-location-of-a-locked-out-User/ - Use PowerShell to Find Locked-Out User Accounts
ttps://blogs.technet.microsoft.com/heyscriptingguy/2011/08/31/use-powershell-to-find-locked-out-User-accounts/ - Hey, Scripting Guy! How Can I Be Notified When a
Process Begins?
http://blogs.technet.com/b/heyscriptingguy/archive/2009/01/19/how-can-i-be-notified-when-a-process-begins.aspx - Build Windows Event Log Watcher Service Process to
Export Event Log Entries as RSS feed
http://www.siccolo.com/Articles/CodeProject/LogWatcher_RSS_feed/build_log_watcher_rss_feed.html - Remote Event Log Montior/Watcher (using TCP in .NET)
http://www.siccolo.com/Articles/CodeProject/Build_Event_Log_Watcher/how-to-Build_Event_Log_Watcher.html - How to
Build Simple Event Log Montior/Watcher (using TCP in .NET)
http://www.codeproject.com/KB/vb/BuildEventLogMonitor.aspx - Use Windows Management Instrumentation (WMI) - Win32_NTLogEvent and
ManagementEventWatcher - to Build Windows Event Log Watcher Service Process to
Export Event Log Entries as RSS feed
http://www.siccolo.com/Articles/CodeProject/LogWatcher_RSS_feed/build_log_watcher_rss_feed_using_WMI.html -
How to Build Remote Event Log Monitor/Watcher (using TCP in .NET)
http://www.siccolo.com/Articles/CodeProject/Build_Event_Log_Watcher/how-to-Build_Event_Log_Watcher.html
Weitere Links
- Get-WinEvent
http://technet.microsoft.com/de-de/library/dd367894.aspx - PowerShell: Get-WinEvent vs.
Get-EventLog
http://www.mcbsys.com/techblog/2011/04/PowerShell-get-winevent-vs-get-eventlog/ - Quick Forensics of Windows
Event Logs (DeepBlueCLI)
https://github.com/sans-blue-team/DeepBlueCLI - Chainsaw: Rapidly Search and
Hunt through Windows Forensic
Artefacts
https://github.com/WithSecureLabs/chainsaw - Quick Forensics of Windows
Event Logs (DeepBlueCLI)
https://www.youtube.com/watch?v=G8XjSO_eshc