Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
671 views
in Technique[技术] by (71.8m points)

logging - JNA Event Log Reader

I am using the below code to read through the Windows Application Event Log using JNA. I want to be able to specify which event to start at instead of always starting with the first event. Does anyone have any suggestions?

import java.io.IOException;
import com.sun.jna.*;
import com.sun.jna.platform.win32.*;
import com.sun.jna.platform.win32.WinNT.*;
import com.sun.jna.ptr.IntByReference;

public class test {

    public static void main(String[] args) throws NumberFormatException, IOException {

        HANDLE h = Advapi32.INSTANCE.OpenEventLog("ServerName", "Application");
        IntByReference pnBytesRead = new IntByReference();
        IntByReference pnMinNumberOfBytesNeeded = new IntByReference();
        Memory buffer = new Memory(1024 * 64);
        IntByReference pOldestRecord = new IntByReference();
        assertTrue(Advapi32.INSTANCE.GetOldestEventLogRecord(h, pOldestRecord));

        int dwRecord = pOldestRecord.getValue();
        int rc = 0;
        while(true) {
            if (! Advapi32.INSTANCE.ReadEventLog(h, WinNT.EVENTLOG_SEQUENTIAL_READ | WinNT.EVENTLOG_FORWARDS_READ, 
                        0, buffer, (int) buffer.size(), pnBytesRead, pnMinNumberOfBytesNeeded)) {
                rc = Kernel32.INSTANCE.GetLastError();
                if (rc == W32Errors.ERROR_INSUFFICIENT_BUFFER) {
                    buffer = new Memory(pnMinNumberOfBytesNeeded.getValue());
                    continue;
                }                
                break;
            }
            int dwRead = pnBytesRead.getValue();
            Pointer pevlr = buffer;
            while (dwRead > 0) 
            {
                EVENTLOGRECORD record = new EVENTLOGRECORD(pevlr);
                System.out.println(dwRecord + " Event ID: " + record.EventID.intValue());

                dwRecord++;
                dwRead -= record.Length.intValue();
                pevlr = pevlr.share(record.Length.intValue());
            }
       }
       assertTrue(rc == W32Errors.ERROR_HANDLE_EOF);
       assertTrue(Advapi32.INSTANCE.CloseEventLog(h));        
   }


   private static void assertTrue(boolean getOldestEventLogRecord) {
   }

}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Bondo, here is a possible solution. In my test, it reads all 570 event logs under Application event; each event log will display in detail its event log record data.

Code solution:

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.Arrays;

import com.sun.jna.*;
import com.sun.jna.platform.win32.*;
import com.sun.jna.platform.win32.WinNT.*;
import com.sun.jna.ptr.IntByReference;

public class Test {

    public static void main(String[] args) throws NumberFormatException, IOException {

        HANDLE h = com.sun.jna.platform.win32.Advapi32.INSTANCE.OpenEventLog(null, "Application");
        IntByReference pnBytesRead = new IntByReference();
        IntByReference pnMinNumberOfBytesNeeded = new IntByReference();

        IntByReference pOldestRecord = new IntByReference();
        assertTrue(com.sun.jna.platform.win32.Advapi32.INSTANCE.GetOldestEventLogRecord(h, pOldestRecord));
        int dwRecord = pOldestRecord.getValue();
        System.out.println("OLD: " + dwRecord);
        IntByReference pRecordCount = new IntByReference();
        assertTrue(com.sun.jna.platform.win32.Advapi32.INSTANCE.GetNumberOfEventLogRecords(h, pRecordCount));
        int dwRecordCnt = pRecordCount.getValue();
        System.out.println("CNT: " + dwRecordCnt);

        int bufSize = 0x7ffff; //(r.size()) * 2048;
        Memory buffer = new Memory(bufSize);
        int rc = 0;
        int cnt = 0;
        while(com.sun.jna.platform.win32.Advapi32.INSTANCE.ReadEventLog(h, 
                WinNT.EVENTLOG_SEEK_READ  /*
                | WinNT.EVENTLOG_SEQUENTIAL_READ */ 
                | WinNT.EVENTLOG_FORWARDS_READ /*
                | WinNT.EVENTLOG_BACKWARDS_READ*/
                , 
                dwRecord, buffer, 
                bufSize, 
                pnBytesRead, 
                pnMinNumberOfBytesNeeded)) {

            rc = Kernel32.INSTANCE.GetLastError();
            if (rc == W32Errors.ERROR_INSUFFICIENT_BUFFER) {
                break;
            }        

            int dwRead = pnBytesRead.getValue();
            Pointer pevlr = buffer;

            while (dwRead > 0) 
            {
                cnt++;
                EVENTLOGRECORD record = new EVENTLOGRECORD(pevlr);
                System.out.println("------------------------------------------------------------");
                System.out.println(cnt+". " + dwRecord + " Event ID: " + record.EventID.shortValue() + " SID: " + record.UserSidLength);

                dwRecord++;

                // WCHAR SourceName[]
                // WCHAR Computername[]
                {
                    ByteBuffer names = pevlr.getByteBuffer(record.size(), 
                            (record.UserSidLength.intValue() != 0 ? record.UserSidOffset.intValue() : record.StringOffset.intValue()) - record.size());
                    names.position(0);
                    CharBuffer namesBuf = names.asCharBuffer();
                    String[] splits = namesBuf.toString().split("");
                    System.out.println("SOURCE NAME: 
" + splits[0]);
                    System.out.println("COMPUTER NAME: 
" + splits[1]);
                }
                // SID   UserSid
                if (record.UserSidLength.intValue() != 0){
                    ByteBuffer sid = pevlr.getByteBuffer(record.UserSidOffset.intValue(), record.UserSidLength.intValue());
                    sid.position(0);
                    //CharBuffer sidBuf = sid.asCharBuffer();
                    byte[] dst = new byte[record.UserSidLength.intValue()];
                    sid.get(dst);
                    System.out.println("SID: 
" + Arrays.toString(dst));
                }
                else {
                    System.out.println("SID: 
N/A");
                }
                // WCHAR Strings[]
                {
                    ByteBuffer strings = pevlr.getByteBuffer(record.StringOffset.intValue(), record.DataOffset.intValue() - record.StringOffset.intValue());
                    strings.position(0);
                    CharBuffer stringsBuf = strings.asCharBuffer();
                    System.out.println("STRINGS["+record.NumStrings.intValue()+"]: 
" + stringsBuf.toString());
                }
                // BYTE  Data[]
                {
                    ByteBuffer data = pevlr.getByteBuffer(record.DataOffset.intValue(), record.DataLength.intValue());
                    data.position(0);
                    CharBuffer dataBuf = data.asCharBuffer();
                    System.out.println("DATA: 
" + dataBuf.toString());
                }
                // CHAR  Pad[]
                // DWORD Length;

                dwRead -= record.Length.intValue();
                pevlr = pevlr.share(record.Length.intValue());
            }
        }
        assertTrue(rc == W32Errors.ERROR_HANDLE_EOF);
        assertTrue(com.sun.jna.platform.win32.Advapi32.INSTANCE.CloseEventLog(h));        
    }


    private static void assertTrue(boolean getOldestEventLogRecord) {

    }

}

Sample output (the last of the event logs):

------------------------------------------------------------
570. 26957 Event ID: 107 SID: 0
SOURCE NAME: 
Report Server Windows Service (VOSTRO)
COMPUTER NAME: 
CVS
SID: 
N/A
STRINGS[1]: 
Report Server Windows Service (VOSTRO)
DATA: 

Notes:

I've set the lpBuffer at its maximum size of 0x7FFFF bytes.

It uses WinNT.EVENTLOG_SEEK_READ mode with the record number offset dwRecordOffset starts at the oldest record number.

The while loop will break when ReadEventLog() method returns zero and its GetLastError() returns W32Errors.ERROR_INSUFFICIENT_BUFFER.

The event id should be read in short for the correct value: record.EventID.shortValue()


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...