是否可以使用VBA代码读取Windows事件查看器?
我希望能够从VBA代码中读取Windows事件查看器项目(例如,当用户登录或注销其工作站时)十多年前,我从某个地方下载了一个代码示例。不幸的是,我不能提供作者的名字或来源,以给予信贷的地方,信贷到期。下面是封装事件日志读取的模块。这是一个示例项目的一部分,我上传了该项目,以便您了解如何使用该模块。这可能不是你想要的,但它应该给你一个良好的开端是否可以使用VBA代码读取Windows事件查看器?,vba,event-viewer,Vba,Event Viewer,我希望能够从VBA代码中读取Windows事件查看器项目(例如,当用户登录或注销其工作站时)十多年前,我从某个地方下载了一个代码示例。不幸的是,我不能提供作者的名字或来源,以给予信贷的地方,信贷到期。下面是封装事件日志读取的模块。这是一个示例项目的一部分,我上传了该项目,以便您了解如何使用该模块。这可能不是你想要的,但它应该给你一个良好的开端 Option Explicit Private Const EVENTLOG_SEQUENTIAL_READ = &H1 Private Co
Option Explicit
Private Const EVENTLOG_SEQUENTIAL_READ = &H1
Private Const EVENTLOG_SEEK_READ = &H2
Private Const EVENTLOG_FORWARDS_READ = &H4
Private Const EVENTLOG_BACKWARDS_READ = &H8
Private Type EVENTLOGRECORD
Length As Long 'Length of full record
Reserved As Long 'Used by the service
RecordNumber As Long 'Absolute record number
TimeGenerated As Long 'Seconds since 1-1-1970
TimeWritten As Long 'Seconds since 1-1-1970
EventID As Long
EventType As Integer
NumStrings As Integer
EventCategory As Integer
ReservedFlags As Integer 'For use with paired events (auditing)
ClosingRecordNumber As Long 'For use with paired events (auditing)
StringOffset As Long 'Offset from beginning of record
UserSidLength As Long
UserSidOffset As Long
DataLength As Long
DataOffset As Long 'Offset from beginning of record
End Type
Private Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (dst As Any, src As Any, ByVal Size As Long)
Private Declare Function OpenEventLog Lib "advapi32" Alias "OpenEventLogA" (ByVal lpUNCServerName As String, ByVal lpEventSourceName As String) As Long
Private Declare Function CloseEventLog Lib "advapi32.dll" (ByVal hEventLog As Long) As Long
Private Declare Function GetNumberOfEventLogRecords Lib "advapi32.dll" (ByVal hEventLog As Long, NumberOfRecords As Long) As Long
Private Declare Function ReadEventLog Lib "advapi32.dll" Alias "ReadEventLogA" (ByVal hEventLog As Long, ByVal dwReadFlags As Long, ByVal dwRecordOffset As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, pnBytesRead As Long, pnMinNumberOfBytesNeeded As Long) As Long
Public Function ReadEvents(ByVal ServerName As String, ByVal EventType As String) As String
'Returns the eventlog content as a vbcrlf separated string
Dim ret As Long, EventLogHwd As Long, EvtRecNo As Long, rBytesRead As Long, rBytesNeeded As Long
Dim rBuff As EVENTLOGRECORD, EvtReadFlags As Long
Dim eBuff() As Byte, StrucLen As Long, EvtRecLen As Long
Dim strBuffer As String, strStart As Long, strStop As Long, strCount As Long, eBytePointer As Long
Dim eSourceName As String, eComputerName As String, ThisString As String
Dim tmpString As String
StrucLen = Len(rBuff)
ReDim eBuff(16384)
EvtReadFlags = EVENTLOG_SEQUENTIAL_READ Or EVENTLOG_FORWARDS_READ
EventLogHwd = OpenEventLog(ServerName, EventType)
If EventLogHwd = 0 Then Exit Function
ret = GetNumberOfEventLogRecords(EventLogHwd, EvtRecNo)
If ret = 0 Then Exit Function
Do While rBuff.RecordNumber < EvtRecNo
'Reads all events in 16K chunks
ret = ReadEventLog(EventLogHwd, EvtReadFlags, rBuff.RecordNumber + 1, eBuff(0), 16384, rBytesRead, rBytesNeeded)
If ret = 0 Then Exit Function
eBytePointer = 0
Do While eBytePointer < rBytesRead
CopyMem rBuff, eBuff(eBytePointer), StrucLen
EvtRecLen = rBuff.Length
'Here rBuff is already filled, then we can filter events
strBuffer = Space(EvtRecLen - StrucLen)
CopyMem ByVal strBuffer, eBuff(StrucLen + eBytePointer), (EvtRecLen - StrucLen)
eBytePointer = eBytePointer + EvtRecLen
strStart = 1
strStop = InStr(strStart, strBuffer, Chr(0))
eSourceName = Mid(strBuffer, strStart, strStop - strStart)
strStart = strStop + 1
strStop = InStr(strStart, strBuffer, Chr(0))
eComputerName = Mid(strBuffer, strStart, strStop - strStart)
'Put all strings together, we can parse later...
If rBuff.NumStrings > 0 Then
strStart = rBuff.StringOffset - StrucLen + 1
ThisString = ""
For strCount = 1 To rBuff.NumStrings
strStop = InStr(strStart, strBuffer, Chr(0))
ThisString = ThisString & Mid(strBuffer, strStart, strStop - strStart) & " "
strStart = strStop + 1
Next strCount
'Here 'ThisString' contains all strings of the current event
If Len(tmpString) > 0 Then
tmpString = tmpString & vbCrLf
End If
tmpString = tmpString & "(Source: " & eSourceName & ") " & ThisString
End If
Loop
Loop
ret = CloseEventLog(EventLogHwd)
ReadEvents = tmpString
End Function
选项显式
Private Const EVENTLOG\u SEQUENTIAL\u READ=&H1
Private Const EVENTLOG\u SEEK\u READ=&H2
Private Const EVENTLOG\u FORWARDS\u READ=&H4
Private Const EVENTLOG\u BACKWARDS\u READ=&H8
私有类型事件日志记录
长度等于完整记录的长度
保留为服务使用的“长”
记录编号为“长”绝对记录编号
自1970年1月1日以来生成的时间为“秒”
自1970年1月1日起写入的时间为“秒”
EventID尽可能长
EventType为整数
作为整数的numstring
EventCategory为整数
ReservedFlags As Integer'用于成对事件(审核)
ClosingRecordNumber As Long'用于成对事件(审核)
StringOffset作为“从记录开始的长偏移量”
UserSidLength尽可能长
UserSidOffset尽可能长
数据长度等于
数据偏移量作为“从记录开始的长偏移量”
端型
私有声明子copymemlib“kernel32”别名“rtlmovemory”(dst为任意,src为任意,ByVal大小为任意长)
私有声明函数OpenEventLog Lib“advapi32”别名“OpenEventLogA”(ByVal lpUNCServerName作为字符串,ByVal lpEventSourceName作为字符串),长度为
私有声明函数CloseEventLog Lib“advapi32.dll”(ByVal hEventLog作为Long)作为Long
私有声明函数GetNumberOfEventLogRecords Lib“advapi32.dll”(ByVal hEventLog为Long,NumberOfRecords为Long)为Long
私有声明函数ReadEventLog Lib“advapi32.dll”别名“ReadEventLogA”(ByVal hEventLog为长,ByVal dwReadFlags为长,ByVal dwRecordOffset为长,lpBuffer为长,ByVal nNumberOfBytesToRead为长,pnBytesRead为长,PnMinNumberOfBytes为长)为长
公共函数ReadEvents(ByVal ServerName作为字符串,ByVal EventType作为字符串)作为字符串
'以vbcrlf分隔字符串的形式返回事件日志内容
Dim ret为Long,EventLogHwd为Long,EvtRecNo为Long,rBytesRead为Long,RBytesNeed为Long
将rBuff变暗为事件日志记录,将EVTRADE标记变长
Dim eBuff()为字节,StrucLen为长,EvtRecLen为长
Dim strBuffer为字符串、strStart为长、strStop为长、strCount为长、eBytePointer为长
Dim eSourceName作为字符串,eComputerName作为字符串,ThisString作为字符串
将tmpString设置为字符串
StrucLen=Len(rBuff)
ReDim eBuff(16384)
EVTRADEFLAGS=EVENTLOG\u SEQUENTIAL\u READ或EVENTLOG\u FORWARDS\u READ
EventLogHwd=OpenEventLog(服务器名,事件类型)
如果EventLogHwd=0,则退出函数
ret=GetNumberOfEventLogRecords(EventLogHwd,EvtRecNo)
如果ret=0,则退出函数
当rBuff.RecordNumber0,则
strStart=rBuff.StringOffset-StrucLen+1
ThisString=“”
对于strCount=1到rBuff.NumStrings
strStop=InStr(strStart,strBuffer,Chr(0))
ThisString=ThisString&Mid(strBuffer、strStart、strStop-strStart)和“”
strStart=strStop+1
下一个strCount
'此处'ThisString'包含当前事件的所有字符串
如果Len(tmpString)>0,则
tmpString=tmpString&vbCrLf
如果结束
tmpString=tmpString&“(源:&eSourceName&”)和此字符串
如果结束
环
环
ret=CloseEventLog(EventLogHwd)
ReadEvents=tmpString
端函数
十多年前,我从某处下载了一个代码示例。不幸的是,我不能提供作者的名字或来源,以给予信贷的地方,信贷到期。下面是封装事件日志读取的模块。这是一个示例项目的一部分,我上传了该项目,以便您了解如何使用该模块。这可能不是你想要的,但它应该给你一个良好的开端
Option Explicit
Private Const EVENTLOG_SEQUENTIAL_READ = &H1
Private Const EVENTLOG_SEEK_READ = &H2
Private Const EVENTLOG_FORWARDS_READ = &H4
Private Const EVENTLOG_BACKWARDS_READ = &H8
Private Type EVENTLOGRECORD
Length As Long 'Length of full record
Reserved As Long 'Used by the service
RecordNumber As Long 'Absolute record number
TimeGenerated As Long 'Seconds since 1-1-1970
TimeWritten As Long 'Seconds since 1-1-1970
EventID As Long
EventType As Integer
NumStrings As Integer
EventCategory As Integer
ReservedFlags As Integer 'For use with paired events (auditing)
ClosingRecordNumber As Long 'For use with paired events (auditing)
StringOffset As Long 'Offset from beginning of record
UserSidLength As Long
UserSidOffset As Long
DataLength As Long
DataOffset As Long 'Offset from beginning of record
End Type
Private Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (dst As Any, src As Any, ByVal Size As Long)
Private Declare Function OpenEventLog Lib "advapi32" Alias "OpenEventLogA" (ByVal lpUNCServerName As String, ByVal lpEventSourceName As String) As Long
Private Declare Function CloseEventLog Lib "advapi32.dll" (ByVal hEventLog As Long) As Long
Private Declare Function GetNumberOfEventLogRecords Lib "advapi32.dll" (ByVal hEventLog As Long, NumberOfRecords As Long) As Long
Private Declare Function ReadEventLog Lib "advapi32.dll" Alias "ReadEventLogA" (ByVal hEventLog As Long, ByVal dwReadFlags As Long, ByVal dwRecordOffset As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, pnBytesRead As Long, pnMinNumberOfBytesNeeded As Long) As Long
Public Function ReadEvents(ByVal ServerName As String, ByVal EventType As String) As String
'Returns the eventlog content as a vbcrlf separated string
Dim ret As Long, EventLogHwd As Long, EvtRecNo As Long, rBytesRead As Long, rBytesNeeded As Long
Dim rBuff As EVENTLOGRECORD, EvtReadFlags As Long
Dim eBuff() As Byte, StrucLen As Long, EvtRecLen As Long
Dim strBuffer As String, strStart As Long, strStop As Long, strCount As Long, eBytePointer As Long
Dim eSourceName As String, eComputerName As String, ThisString As String
Dim tmpString As String
StrucLen = Len(rBuff)
ReDim eBuff(16384)
EvtReadFlags = EVENTLOG_SEQUENTIAL_READ Or EVENTLOG_FORWARDS_READ
EventLogHwd = OpenEventLog(ServerName, EventType)
If EventLogHwd = 0 Then Exit Function
ret = GetNumberOfEventLogRecords(EventLogHwd, EvtRecNo)
If ret = 0 Then Exit Function
Do While rBuff.RecordNumber < EvtRecNo
'Reads all events in 16K chunks
ret = ReadEventLog(EventLogHwd, EvtReadFlags, rBuff.RecordNumber + 1, eBuff(0), 16384, rBytesRead, rBytesNeeded)
If ret = 0 Then Exit Function
eBytePointer = 0
Do While eBytePointer < rBytesRead
CopyMem rBuff, eBuff(eBytePointer), StrucLen
EvtRecLen = rBuff.Length
'Here rBuff is already filled, then we can filter events
strBuffer = Space(EvtRecLen - StrucLen)
CopyMem ByVal strBuffer, eBuff(StrucLen + eBytePointer), (EvtRecLen - StrucLen)
eBytePointer = eBytePointer + EvtRecLen
strStart = 1
strStop = InStr(strStart, strBuffer, Chr(0))
eSourceName = Mid(strBuffer, strStart, strStop - strStart)
strStart = strStop + 1
strStop = InStr(strStart, strBuffer, Chr(0))
eComputerName = Mid(strBuffer, strStart, strStop - strStart)
'Put all strings together, we can parse later...
If rBuff.NumStrings > 0 Then
strStart = rBuff.StringOffset - StrucLen + 1
ThisString = ""
For strCount = 1 To rBuff.NumStrings
strStop = InStr(strStart, strBuffer, Chr(0))
ThisString = ThisString & Mid(strBuffer, strStart, strStop - strStart) & " "
strStart = strStop + 1
Next strCount
'Here 'ThisString' contains all strings of the current event
If Len(tmpString) > 0 Then
tmpString = tmpString & vbCrLf
End If
tmpString = tmpString & "(Source: " & eSourceName & ") " & ThisString
End If
Loop
Loop
ret = CloseEventLog(EventLogHwd)
ReadEvents = tmpString
End Function
选项显式
Private Const EVENTLOG\u SEQUENTIAL\u READ=&H1
Private Const EVENTLOG\u SEEK\u READ=&H2
Private Const EVENTLOG\u FORWARDS\u READ=&H4
Private Const EVENTLOG\u BACKWARDS\u READ=&H8
私有类型事件日志记录
长度等于完整记录的长度
保留为服务使用的“长”
记录编号为“长”绝对记录编号
自1970年1月1日以来生成的时间为“秒”
时间写得一样长