I've been testing the UDF below with KiXtart and I've found that it apparently does not support semisynchronous queries with WMI. Semisynchronous queries are faster and require less memory overhead on the queried computer. These queries are generated through a ExecQuery($query,'WQL',48) call.

When uncommenting the line that activates semisynchronous queries, the UDF still works without raising an error message. However, all array fields are empty even though the correct number of rows/columns are returned.

code:
; some test code first
$events = ReadEventlog('Security',528,@WKSTA,'2003/03/01 00:00:00')
? ubound($events,1)
? ubound($events,2)
for $a=0 to ubound($events,1)
for $b=0 to ubound($events,2)
? 'Events['+$a+','+$b+'] = '+$events[$a,$b]
next
next
$rc='SELECT TimeGenerated, User FROM Win32_NTLogEvent WHERE Logfile="System" AND TimeGenerated>="20030225000000.000000-300"'
$events = ReadEventlog($rc)
? ubound($events,1)
? ubound($events,2)
for $a=0 to ubound($events,1)
for $b=0 to ubound($events,2)
? 'Events['+$a+','+$b+'] = '+$events[$a,$b]
next
next

; here's the UDF

;FUNCTION ReadEventlog()
;
;ACTION Retrieves events from the eventlog
;
;AUTHOR Jens Meyer
;
;VERSION 1.4
;
;KIXTART VER 4.20
;
;SYNTAX RETCODE = READEVENTLOG(EVENTLOG, EVENTID, OPTIONAL COMPUTER, OPTIONAL DATETIME,
; OPTIONAL USERNAME, OPTIONAL PASSWORD)
;
;PARAMETERS EVENTLOG
; Name of the eventlog, e.g. 'Security', 'System','Application'
; Alternatively, a custom WQL query can be provided. Date fields in
; a WQL query MUST be properly formatted as YYYY/MM/DD HH:MM:SS:000
;
; EVENTID
; Optional Event ID number to be retrieved
;
; COMPUTER
; optional name of a remote computer which eventlog is to be queried. If no
; username/password is provided then the current users credentials will be
; used to connect to the remote event log.
;
; DATETIME
; optional date/time string denoting the start date of the events in
; the form of YYYY/MM/DD HH:MM:SS, YYY/MM/DD, or HH:MM:SS
;
; USERNAME
; optional username which will be used to connect to a remote computer
;
; PASSWORD
; optional password which will be used to connect to the remote computer
;
;RETURN array of events or empty string
;
;REMARKS returns a 2-dimensional array with the following columns. If custom WQL is
; used, then the SELECT part of the custom WQL determines the field assignments.
;
; Column 0 = Category
; Column 1 = CategoryString
; Column 2 = ComputerName
; Column 3 = Data
; Column 4 = EventCode
; Column 5 = EventIdentifier
; Column 6 = EventType
; Column 7 = InsertionStrings
; Column 8 = Logfile
; Column 9 = Message
; Column 10 = RecordNumber
; Column 11 = Source Name
; Column 12 = TimeGenerated
; Column 13 = TimeWritten
; Column 14 = Type
; Column 15 = User
;
;DEPENDENCIES WMI
;
;EXAMPLE $events = ReadEventlog('Security',528)
; $events = ReadEventlog('Security',528,,'COMPUTER')
; $events = ReadEventlog('Security',528,'2002/09/01 00:00:00','COMPUTER','Administrator','password')
; $events = ReadEventlog('SELECT TimeGenerated, User FROM Win32_NTLogEvent
; WHERE Logfile="Security" AND EventCode=528 AND
; TimeGenerated>="2002/09/01 00:00:00:000"'
;
;KIXTART BBS http://www.kixtart.org/cgi-bin/ultimatebb.cgi?ubb=get_topic&f=12&t=000270
;
function ReadEventlog($eventlog, optional $eventid, optional $computer, optional $datetime, optional $username, optional $password)
dim $objLocator, $objWBEM, $objWMIResults, $namespace
dim $event, $item, $wqlQuery, $eventarray
dim $customwql, $customfields, $field
dim $rownumber, $arrayrows, $arraycolumns, $columnnumber
dim $byte, $datastring, $date, $time, $querydate, $querytime, $timezone
dim $objWMIService, $colItems, $objItem

$namespace = 'root\CIMV2'

if trim($eventlog)=''
exit 87
endif

; check to see whether we're connecting to a local or remote eventlog
$computer=trim($computer)
select
case $computer=@WKSTA
$computer='.'
case $computer
case 1
$computer='.'
endselect

if $username and $computer<>'.'
; create locator object for connection to a remote computer
$objLocator = CreateObject('WbemScripting.SWbemLocator')
if @ERROR
exit @ERROR
endif
; create a (credentialed, if username/password provided) connection to a remote computer
$objWBEM=$objLocator.ConnectServer($computer,$namespace,$username,$password)
if @ERROR
exit @ERROR
endif
; set the impersonation level
$objWBEM.Security_.ImpersonationLevel = 3
if @ERROR
exit @ERROR
endif
else
;set the impersonation level and make sure we have security permissions
if $eventlog='Security'
$objWBEM=GetObject('winmgmts:{impersonationLevel=impersonate, (Security)}!\\'+$computer+'\'+$namespace)
else
$objWBEM=GetObject('winmgmts:{impersonationLevel=impersonate}!\\'+$computer+'\'+$namespace)
endif
if @ERROR
exit @ERROR
endif
endif

; check to see whether we're looking for an event ID or if there's a custom query
if left($eventlog,6)='select'
$wqlquery=$eventlog
$arraycolumns=trim(substr($wqlquery,instr($wqlquery,' ')+1,instr($wqlquery,'FROM')-instr($wqlquery,' ')-2))
if instr($arraycolumns,'*')
$arraycolumns=16
$customwql=0
else
$customfields=split(trim($arraycolumns),',')
for $arraycolumns=0 to ubound($customfields)
$customfields[$arraycolumns]=trim($customfields[$arraycolumns])
next
$arraycolumns=ubound($customfields)+1
$customwql=1
endif
else
$customwql=0
$arraycolumns=16
$eventid=val($eventid)
$wqlQuery="SELECT * FROM Win32_NTLogEvent WHERE Logfile='"+$eventlog+"' AND EventCode="+val($eventID)

if $datetime
$colItems = $objWBEM.ExecQuery('Select CurrentTimeZone from Win32_ComputerSystem')
if @ERROR
exit @ERROR
endif

for each $objItem in $colItems
$timezone = $objItem.CurrentTimeZone
next

$objWMIService = 0
$colItems = 0
$objItem = 0

$datetime=trim($datetime)

select
case instr($datetime,' ')
$date=left($datetime,instr($datetime,' ')-1)
$time=substr($datetime,instr($datetime,' ')+1)
case instr($datetime,'/')
$date=$datetime
$time='00:00:00'
case instr($datetime,':')
$date=@DATE
$time=$datetime
case 1
$date=@DATE
$time=@TIME
endselect
if $date and $time
$datetime=join(split($date,'/'),'')+join(split($time,':'),'')+'.000000'+$timezone
else
$datetime=''
endif

$wqlQuery=$wqlQuery+' AND TimeGenerated>="'+$datetime+'"'
endif
endif

;------------------------------------------
;| beginning of problematic code fragment |
;------------------------------------------

; the following line would not work
; $objWMIResults = $objWBEM.ExecQuery($wqlQuery,'WQL',48)
; this line would work
; $objWMIResults = $objWBEM.ExecQuery($wqlQuery,'WQL',0)
; this line would work
$objWMIResults = $objWBEM.ExecQuery($wqlQuery)

;------------------------------------------
;| end of problematic code fragment |
;------------------------------------------


if @ERROR
exit @ERROR
endif

$rownumber = 0
$columnnumber = 0
; this is for semisyncronous queries
$arrayrows=0
for each $event in $objWMIResults
$arrayrows=$arrayrows+1
next
; otherwise, this could be used for non-semisynchronous queries
;$arrayrows = val($objWMIResults.Count)

if $arrayrows=0
$ReadEventlog=''
return
endif

redim $eventarray[$arrayrows-1,$arraycolumns-1]

for each $event in $objWMIResults
$columnnumber = 0
for each $item in $event.Properties_
if $customwql=0 or ascan($customfields,$item.name)+1
select
case $item.Name='Data'
$datastring=''
for each $byte in $event.Data
if $byte=0
$byte=46
endif
$datastring=$datastring+chr($byte)
next
$eventarray[$rownumber,$columnnumber]=$datastring
case $item.name='InsertionStrings'
$eventarray[$rownumber,$columnnumber]=join($item.Value,@CRLF)
case $item.name='TimeGenerated' or $item.Name='TimeWritten'
$time=left($item.Value,4)+'/'+substr($item.Value,5,2)+'/'+substr($item.Value,7,2)+' '
$time=$time+substr($item.Value,9,2)+':'+substr($item.Value,11,2)+':'+substr($item.Value,13,2)
$eventarray[$rownumber,$columnnumber]=$time
case 1
$eventarray[$rownumber,$columnnumber]=$item.Value
endselect
$columnnumber=$columnnumber+1
endif
next
$rownumber=$rownumber+1
next

$objWMIResults = 0
$objWBEM = 0
$objLocator = 0
$ReadEventlog = $eventarray
exit 0

endfunction



[ 02. March 2003, 01:35: Message edited by: sealeopard ]
_________________________
There are two types of vessels, submarines and targets.