package require tcl 8.6
package require tcom
namespace eval ::eventLog {
variable types;
variable columns;
variable hexMap
unset -nocomplain types columns hexMap;
proc RecordsToList {records} {
variable types;
variable columns;
set list [list];
try {
if {![info exists types]} {
# create the record-tcl type mapping
#
set types [list \
[$records REAL_TYPE] {
set type double;
set command getValue;
set eval "";
} \
[$records INTEGER_TYPE] {
set type integer;
set command getValue;
set eval "";
} \
[$records TIMESTAMP_TYPE] {
set type timestamp;
set command toNativeString;
set eval [list apply [list {value} {
return [clock scan $value -format {%Y-%m-%d %H:%M:%S}];
} [namespace current]]];
} \
[$records NULL_TYPE] {
set type NULL;
set command getValue;
set eval "";
} \
[$records STRING_TYPE] - \
default {
set type string;
set command getValue;
set eval "";
} \
];
}
if { ![info exists columns]
|| [$records getColumnCount] != [dict size $columns]} {
# create the columns data set
#
set columns [dict create];
for {set i 0; set end [$records getColumnCount]} {$i < $end} {incr i} {
set column [dict create name "" type "" command "" eval ""];
dict with column {
set name [$records getColumnName $i];
switch [$records getColumnType $i] $types;
switch $name {
EvntType {
set name EventTypeName;
set eval [list apply [list {value} {return [string tolower $value];} [namespace current]]];
}
EventCategoryName {
set eval [list apply [list {value} {
return [expr {[string first {The name for category } $value] == -1 ? $value : ""}];
} [namespace current]]];
}
Message {
set eval [list apply [list {value} {return [string trim $value];} [namespace current]]];
}
Data {
set eval [list apply [list {value} {
variable hexMap;
if {![info exists hexMap]} {
for {set i 0} {$i < 256} {incr i} {
lappend hexMap [format {%02X} $i] [format {%c} $i];
}
}
set value [string map $hexMap $value];
if {[string first "\x0" $value] >= 0} {
if {[string first "\x0\x0" $value] == -1} {
set temp [string trim [encoding convertfrom unicode $value]];
if {[string is print -strict $temp]} {
set value $temp;
}
}
} else {
set value [string trim $value];
}
return $value;
} [namespace current]]];
}
}
};
dict set columns $i $column;
}
}
# convert the records set into a tcl list of dictionaries
#
set list [list];
while {![$records atEnd]} {
set row [dict create];
set record [$records getRecord];
for {set i 0; set end [dict size $columns]} {$i < $end} {incr i} {
set column [dict get $columns $i];
dict with column {
set value "";
if {![$record isNull $i]} {
set value [$record $command $i];
if {$eval ne ""} {
set value [{*}$eval $value];
}
}
dict set row $name $value;
}
}
lappend list $row;
unset record;
$records moveNext;
}
} on error {result options} {
error $result [dict get $options -errorinfo] [dict get $options -errorcode];
} finally {
$records close;
}
return $list;
}
proc get {source types {undefined 0}} {
try {
set lgp [tcom::ref createobject MSUtil.LogQuery];
set evt [tcom::ref createobject MSUtil.LogQuery.EventLogInputFormat];
$evt resolveSIDs 1;
$evt binaryFormat HEX;
set records [$lgp Execute \
[format \
"SELECT
SID,
TO_LOWERCASE(REPLACE_STR(EventTypeName,' event','')) As EvntType,
TimeGenerated,
SourceName,
EventCategoryName,
EventCategory,
EventID,
Message,
Data
FROM %s
WHERE
EvntType IN ('%s')
%s
ORDER BY
EvntType, TimeGenerated DESC" \
$source \
[join [string tolower $types] {';'}] \
[expr {$undefined ? "" : "AND NOT Message LIKE 'The description for Event ID %'"}] \
] \
$evt \
];
set list [RecordsToList $records];
} on error {result options} {
error $result [dict get $options -errorinfo] [dict get $options -errorcode];
} finally {
unset -nocomplain lgp evt records;
}
return $list;
}
namespace export -clear {[a-z]*};
namespace ensemble create;
}
set apps [eventLog get Application {warning error}]; puts "";
set system [eventLog get System {warning error}]; puts "";