Chinaunix首页 | 论坛 | 博客
  • 博客访问: 272198
  • 博文数量: 54
  • 博客积分: 1425
  • 博客等级: 上尉
  • 技术积分: 541
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-27 23:26
文章分类

全部博文(54)

文章存档

2018年(2)

2015年(3)

2014年(6)

2013年(5)

2012年(5)

2011年(7)

2010年(14)

2009年(1)

2008年(3)

2007年(6)

2006年(1)

2005年(1)

我的朋友

分类: WINDOWS

2008-02-23 15:35:37

Windows日志文件具有以下特点:
1、系统启动后,系统日志处于打开状态,它是不能直接修改的,但是可以查询;如若想修改必须处于另一操作系统中修改,或者将其拷出修改,再修改注册表指向修改后的日志文件。
2、系统日志具有顺序存储的结构,包括头记录(48字节),记录项(前4字节为记录长度,其后为记录内容,其中内容为Windows特定长度的二进制信息,由Windows日志程序处理后,信息才连贯显示,否则只是记录的各个字段罗列),尾记录(40字节),后边为填充的00项字节,无意义。
编程中遇到的问题:
1、记录项过多时,不能用checkedlistbox或listbox等控件存储数据,否则,系统在加入数据记录到列表框时,速度越来越慢。所以我改用了DataTable,这个确实较上一个快。
2、Windows API 日志存储数据结构。
typedef struct _EVENTLOGRECORD {
DWORD Length;
DWORD Reserved;
DWORD RecordNumber;
DWORD TimeGenerated;
DWORD TimeWritten;
DWORD EventID;
WORD EventType;
WORD NumStrings;
WORD EventCategory;
WORD ReservedFlags;
DWORD ClosingRecordNumber;
DWORD StringOffset;
DWORD UserSidLength;
DWORD UserSidOffset;
DWORD DataLength;
DWORD DataOffset;
} EVENTLOGRECORD, *PEVENTLOGRECORD;
3、EventID代表不同事件类型,如6008为意外关机
4、EventType有几种不同意义,分别为1 错误\2 警告\4 信息\8 成功审核\10h 失败审核;
5、TimeWritten从1970-1-1 00:00:00开始的秒数,但是中国为第八时区(北京时间)所以开始时间为1970-1-1 08:00:00(我猜的,因为加上8个小时就和日志的时间对上了)
6、下面是我编写的一段用来读取日志记录信息的程序(VB.Net)
    Public Function get_info(ByVal fieldname As String, ByVal i As Integer) As Object
        Dim disp_str, rec_str As String
        Dim byte_str() As String
        disp_str = ""
        rec_str = ""
        TextBox1.Text = ""
        '读取记录信息
        '1、记录长度;
        Dim rec_leng As Integer
        '2、保留;
        '3、记录号;
        Dim rec_num As Integer
        rec_num = 0
        '4、消逝时间;
        Dim time_gene As System.Int32
        time_gene = 0
        '5、写入时间;
        Dim time_writ As System.Int32
        '6、事件编号;
        Dim event_id As System.Int32
        '7、事件类型;
        Dim event_type As Integer
        '8、NumString;
        Dim msg_count As Integer
        '9、EventCategory;
        Dim eventG As System.Int32
        '10、ReservedFlags;
        '11、ClosingRecordNumber;
        Dim CloseRecNum As System.Int64
        '12、StringOffset;
        Dim stroffset As System.Int32
        '13、UserSidLength;
        Dim UserSidLength As System.Int64
        '14、UserSidOffset;
        Dim UserSidOffset As System.Int64
        '15、DataLength;
        Dim DataLen As System.Int64
        '16、DataOffset;
        Dim DataOff As System.Int64
        '17  信息来源 '两项内容计算推得,不用定义
        '18 信息内容
 
        '当前item的二进制内容
        rec_str = filetable.Rows(i)(1).ToString
        '将二进制序列重新编排成字节数组
        byte_str = Split(rec_str, ",")
        '1、提取记录长度
        Dim byte_count As System.Int32
        rec_leng = 0
        Select Case fieldname
            Case "记录长度"
                For byte_count = 0 To 3
                    rec_leng = rec_leng + Convert.ToInt32(byte_str(byte_count)) * (256 ^ byte_count)
                Next
                get_info = rec_leng.ToString
            Case "记录号"
                For byte_count = 8 To 11
                    rec_num = rec_num + Convert.ToInt32(byte_str(byte_count)) * (256 ^ (byte_count - 8))
                Next
                get_info = rec_num.ToString
            Case "消逝时间"
                For byte_count = 12 To 15
                    time_gene = time_gene + Convert.ToInt32(byte_str(byte_count)) * (256 ^ (byte_count - 12))
                Next
                Dim NewDate As DateTime = DateAdd("s", time_gene, "1970-1-1 08:00:00")
                get_info = NewDate.ToString
            Case "写入时间"
                For byte_count = 16 To 19
                    time_writ = time_writ + Convert.ToInt32(byte_str(byte_count)) * (256 ^ (byte_count - 16))
                Next
                Dim NewDate As DateTime = DateAdd("s", time_writ, "1970-1-1 08:00:00")
                get_info = NewDate.ToString
            Case "事件编号"
                For byte_count = 20 To 21
                    event_id = event_id + Convert.ToInt32(byte_str(byte_count)) * (256 ^ (byte_count - 20))
                Next
                get_info = event_id.ToString
            Case "事件类型"
                'Dim str_type As String
                For byte_count = 24 To 25
                    event_type = event_type + Convert.ToInt32(byte_str(byte_count)) * (256 ^ (byte_count - 24))
                Next
                'Select Case event_type
                'Case 1
                '   str_type = " 错误"
                'Case 2
                '   str_type = " 警告"
                'Case 4
                '   str_type = " 信息"
                'Case 8
                '   str_type = " 成功审核"
                'Case 16
                '   str_type = " 失败审核"
                'Case Else
                '   str_type = event_type.ToString
                'End Select
                'disp_info_new = str_type.ToString
                get_info = event_type.ToString
            Case "事件信息量"
                msg_count = 0
                For byte_count = 26 To 27
                    msg_count = msg_count + Convert.ToInt32(byte_str(byte_count)) * (256 ^ (byte_count - 26))
                Next
                get_info = msg_count.ToString
            Case "EventGategory"
                eventG = 0
                For byte_count = 28 To 29
                    eventG = eventG + Convert.ToInt32(byte_str(byte_count)) * (256 ^ (byte_count - 28))
                Next
                get_info = eventG.ToString
            Case "ClosingRecordNumber"
                CloseRecNum = 0
                For byte_count = 32 To 35
                    CloseRecNum = CloseRecNum + Convert.ToInt32(byte_str(byte_count)) * (256 ^ (byte_count - 32))
                Next
                get_info = CloseRecNum.ToString
            Case "StringOffset"
                stroffset = 0
                For byte_count = 36 To 39
                    stroffset = stroffset + Convert.ToInt32(byte_str(byte_count)) * (256 ^ (byte_count - 36))
                Next
                get_info = stroffset.ToString
            Case "UserSidLength"
                UserSidLength = 0
                For byte_count = 40 To 43
                    UserSidLength = UserSidLength + Convert.ToInt64(byte_str(byte_count)) * (256 ^ (byte_count - 40))
                Next
                get_info = UserSidLength.ToString
            Case "UserSidOffset"
                UserSidOffset = 0
                For byte_count = 44 To 47
                    UserSidOffset = UserSidOffset + Convert.ToInt64(byte_str(byte_count)) * (256 ^ (byte_count - 44))
                Next
                get_info = UserSidOffset.ToString
            Case "DataLen"
                DataLen = 0
                For byte_count = 48 To 51
                    DataLen = DataLen + Convert.ToInt64(byte_str(byte_count)) * (256 ^ (byte_count - 48))
                Next
                get_info = DataLen.ToString
            Case "DataOffset"
                DataOff = 0
                For byte_count = 52 To 55
                    DataOff = DataOff + Convert.ToInt64(byte_str(byte_count)) * (256 ^ (byte_count - 52))
                Next
                get_info = DataOff.ToString
            Case "信息来源"
                rec_leng = byte_str.Length
                Dim SourceInfo As String
                SourceInfo = ""
                byte_count = 56
                While byte_count < rec_leng
                    If byte_str(byte_count) = "0" And byte_str(byte_count + 1) = "0" Then
                        byte_count = byte_count + 2
                        Exit While
                    End If
                    SourceInfo = SourceInfo + word_str(byte_str(byte_count), byte_str(byte_count + 1))
                    byte_count = byte_count + 2
                End While
                get_info = SourceInfo.ToString
            Case "计算机名"
                Dim HostName As String
                HostName = ""
                rec_leng = byte_str.Length
                byte_count = 56
                While byte_count < rec_leng
                    If byte_str(byte_count) = "0" And byte_str(byte_count + 1) = "0" Then
                        byte_count = byte_count + 2
                        Exit While
                    End If
                    byte_count = byte_count + 2
                End While
                While byte_count < rec_leng
                    If byte_str(byte_count) = "0" And byte_str(byte_count + 1) = "0" Then
                        byte_count = byte_count + 2
                        Exit While
                    End If
                    HostName = HostName + word_str(byte_str(byte_count), byte_str(byte_count + 1))
                    byte_count = byte_count + 2
                End While
                get_info = HostName
            Case "记录信息"
                Dim MessageContent As String
                stroffset = 0
                MessageContent = ""
                For byte_count = 36 To 39
                    stroffset = stroffset + Convert.ToInt32(byte_str(byte_count)) * (256 ^ (byte_count - 36))
                Next
                byte_count = stroffset
                While byte_count < rec_leng - 4
                    If (byte_str(byte_count) = "0") And (byte_str(byte_count + 1) = "0") And (byte_str(byte_count + 2) = "0") And (byte_str(byte_count + 3) = "0") Then
                        Exit While
                    End If
                    If (byte_str(byte_count) = "0") And (byte_str(byte_count + 1) = "0") Then
                        MessageContent = MessageContent + "-00-"
                    Else
                        MessageContent = MessageContent + word_str(byte_str(byte_count), byte_str(byte_count + 1))
                    End If
                    byte_count = byte_count + 2
                End While
                get_info = MessageContent
            Case Else
                get_info = "无此内容项"
        End Select
    End Function
    Public Sub AddLogItem(ByVal logfilename As String, ByVal dgv As DataGridView)
        '********************************
        Dim filerow As DataRow
        '********************************
        Const rec_len = 8
        Const mem_bs = 524288
        Dim flag_string As String
        Dim mem_byte(mem_bs) As Byte
        Dim mem_cnt, mem_length As Integer '当前记录块的数量-1 ,记录块实际长度
        Dim cur_pos, old_pos As System.Int32        '当前记录文件的指针
        Dim elsp_time As DateTime
        elsp_time = Now
        Dim temp_buffer(1) As Byte
        Dim temp_str As String
        Dim len_buffer(rec_len) As Byte
        Dim content_len As System.Int32
        Dim rec_log As String
        Dim rec_count As System.Int32
        Dim count_total As System.Int32
        mem_cnt = 0
        old_pos = 0
        rec_count = 0
        count_total = 0
        temp_str = ""
        If logfilename.Length = 0 Then
            MessageBox.Show("Error, logfile is empty!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Exit Sub
        End If
        logfile = New FileInfo(logfilename)
        Try
            logfilestream = New FileStream(logfilename, FileMode.OpenOrCreate, FileAccess.ReadWrite)
            While cur_pos < logfilestream.Length
                '读入1MB的文件内容
                If mem_cnt = 0 Then
                    mem_length = logfilestream.Read(mem_byte, 0, mem_bs)
                Else
                    logfilestream.Seek(cur_pos, SeekOrigin.Begin)
                    mem_length = logfilestream.Read(mem_byte, 0, mem_bs)
                End If
                '时间标志
                elsp_time = Now
                TextBox1.Text = TextBox1.Text + elsp_time.ToString + vbCrLf
                TextBox1.Refresh()
                '开始处理这1MB的内容
                Do While count_total < mem_length
                    copybyte(len_buffer, mem_byte, count_total, rec_len)
                    '产生记录的特征串(第5-8字节)
                    flag_string = len_buffer(4).ToString + len_buffer(5).ToString + len_buffer(6).ToString + len_buffer(7).ToString
                    If flag_string = "7610276101" Then
                        temp_str = ""
                        '计算每条记录长度
                        content_len = Convert.ToInt32(len_buffer(0)) + Convert.ToInt32(len_buffer(1)) * 256 + Convert.ToInt32(len_buffer(2)) * 256 * 256 + Convert.ToInt32(len_buffer(3)) * 256 * 256 * 256
                        '对于不能完全从缓冲区中读取的数据转到下一个数据段处理
                        If (count_total + content_len > mem_bs) Then
                            cur_pos = count_total + old_pos
                            old_pos = old_pos + count_total
                            count_total = 0
                            mem_cnt = mem_cnt + 1
                            Exit Do
                        End If
                        Dim count As System.Int32
                        count = 0
                        rec_log = ""
                        '把读出的记录存入字符串数组
                        rec_log = mem_byte(count_total).ToString
                        For count = count_total + 1 To count_total + content_len
                            rec_log = rec_log + "," + mem_byte(count).ToString
                        Next
                        count_total = count_total + content_len
                        '如果为第一条记录则不加入列表框
                        If rec_count > 0 Then
                            filerow = filetable.NewRow
                            filerow.Item(0) = rec_count.ToString
                            filerow.Item(1) = rec_log
                            filetable.Rows.Add(filerow)
                            filerow = Nothing
                        End If
                        rec_count = rec_count + 1
                        ToolStripProgressBar1.Value = ToolStripProgressBar1.Value + content_len
                        '如果缓冲区中的数据正好处理完毕,则读取下一个数据段
                        If count_total = mem_length Then
                            cur_pos = count_total + old_pos
                            old_pos = old_pos + count_total
                            count_total = 0
                            mem_cnt = mem_cnt + 1
                            Exit Do
                        End If
                    Else
                        '后边没有记录时,以0填充,数据不再有意义,即数据已读出,可退出循环!
                        If flag_string = "17171717" Then
                            ToolStripProgressBar1.Value = ToolStripProgressBar1.Maximum
                            Exit While
                        End If
                        '绕过头记录的00填充字节
                        copybyte(temp_buffer, mem_byte, count_total, 1)
                        temp_str = temp_str + temp_buffer.ToString
                        ToolStripProgressBar1.Value = ToolStripProgressBar1.Value + 1
                        count_total = count_total + 1
                    End If
                Loop
            End While
            logfilestream.Close()
            dgv.DataSource = filetable
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
        ToolStripStatusLabel1.Text = filetable.Rows.Count.ToString() + " records is loaded!"  '+ "   checkedlistbox1:" + CheckedListBox1.Items.Count.ToString
    End Sub
    Public Sub copybyte(ByVal desc() As Byte, ByVal source() As Byte, ByVal offset As Integer, ByVal len As Integer)
        '本函数属于无保护的过程,请慎重使用
        Dim i, j As Integer
        For i = offset To offset + len - 1
            desc(j) = source(i)
            j = j + 1
        Next
    End Sub


阅读(6194) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~