MHo: Program for tailing ms windows event logs using twapi. Work in progress. use it in any way you want, but at your own risk. This is the main prog of a starpack which will later be made downloadable somewhere.
package provide app-wineltail 1.0 # wineltail # 18.10.2013 # (c) Matthias Hoffmann # Monitor Windows Event Logs package require twapi_eventlog package require twapi_console ::twapi::import_commands proc trapClose {type} { global hevl hmon hname signal puts stderr $type foreach h [array names hmon] { puts stderr "Stoppe Monitor Instanz $hmon($h) für $hname($h)" catch {eventlog_monitor_stop $hmon($h)} } foreach h [array names hevl] { puts stderr "Schliesse Eventloginstanz $hevl($h) für $hname($h)" catch {eventlog_close $hevl($h)} } set signal 1 } proc formatSID {sid} { if {[string length $sid]} { if {![catch {lookup_account_sid $sid} rc]} { return $rc } } return [string range $sid end-6 end] } proc formatEventID {eid} { # diese merkwürdige Logik muss auch noch gecheckt werden! set e [expr {$eid-1073741824}] if {$e < 0} { set e 1 } return $e } # Idlehandler proc formatOutput {l lbuf} { foreach eventrec $lbuf { array set event $eventrec # $event(-sid) später nur optional!! Bzw. Ausgabe gemäss variabler Schablone. # Verwendung von lookup_account_sid direkt in eventSink führt zum Verschlucken von Events, # daher hier asynchron # [list [string range $event(-sid) end-6 end]] puts "[list [clock format $event(-timegenerated) -format {%Y%m%d %T}]] \ [list $event(-system)] \ [list [formatSID $event(-sid)]] \ [list $l] \ [list $event(-recordnum)] \ [list [string range $event(-type) 0 6]] \ [list $event(-source)] \ [list [eventlog_format_category $eventrec -width -1]] \ [list [formatEventID $event(-eventid)]] \ [list [eventlog_format_message $eventrec -width -1]]" array set event {} } } # der Monitorhandle wird immer als letztes Übergeben (nicht benötigt) # wird nur gefeuert, wenn tatsächlich ein Signal anliegt proc eventSink {e l m} { after idle [list formatOutput $l [eventlog_read $e]]; # asynchron weitermachen } # für eigenes Polling proc eventPoll {e l} { after idle [list formatOutput $l [eventlog_read $e]]; # asynchron weitermachen after 5000 [info level 1]; # später Intervall bestimmbar machen } if {$argc == 0} { puts stderr {Parameter: (engl.) Name(n) der zu überwachenden Eventquelle(n), Bsp.: System Es können mehrere Quellen angegeben werden, Bsp.: System Application Es kann je Quelle ein Systemname angegeben werden, Bsp.: "System Matthias" Application (in diesem Fall wird versucht, die System-Events vom remote Rechner Matthias zu lesen, und Application-Events vom lokalen Rechner). Das Auflösen von Benutzernamen funktioniert ggF. nicht. Es werden dann die letzten Stellen der SID zurückgegeben. Das Programm kann mit Strg+C beendet werden. } exit 255 } set_console_control_handler [list trapClose] set ix 0 array set hevl {} array set hmon {} array set hname {} foreach log $argv { if {[llength $log] == 2} { set logname [lindex $log 0] set logsys [lindex $log 1] } else { set logname $log set logsys $::env(computername) } if {![catch {set hevl($ix) [eventlog_open -source $logname -system $logsys]} rc]} { if {[catch { # zu Beginn die jüngsten 10 Sätze je Log anzeigen formatOutput $logname [twapi::eventlog_read $hevl($ix) -seek [expr {[twapi::eventlog_oldest $hevl($ix)]+[twapi::eventlog_count $hevl($ix)]-10}]] if {[catch {set hmon($ix) [eventlog_monitor_start $hevl($ix) [list eventSink $hevl($ix) $logname]]}]} { # Monitoring auf remote_logs funktioniert nicht, also in diesem Falle eigenes Polling eventPoll $hevl($ix) $logname } set hname($ix) "$logsys $logname"; # nur für Anzeige beim späteren Schließen incr ix } rc]} { puts stderr "(2) $rc" } } else { puts stderr "(1) $rc"; # im Heimnetz nicht testbar!? ("der RPC-Server ist nicht verfpgbar") } } if {$ix == 0} { puts stderr "Es konnten keine Logs geöffnet werden!" exit 1 } vwait signal exit 0