我已经创建了一个小程序(服务或控制台,对它们进行了相同的测试,以观察它们的结果),仅在Windows安全事件日志中查找某些事件ID,然后在该ID通过的最后一次事件上执行操作。
这可以正常工作一段时间,然后突然,一天几次,程序运行并获取整个日志中具有指定事件ID的所有事件(而不仅仅是最后一个)。
这是我的代码:
class Program
{ // These are the events I want to listen to
public static string[] eventsToListen = { "4727", "4730", "5136", "5139" };
static void Main(string[] args)
{
EventLog eventLog = new EventLog("Security", Environment.MachineName);
eventLog.EntryWritten += new EntryWrittenEventHandler(OnEntryWrittenAsync);
eventLog.EnableRaisingEvents = true;
Console.ReadLine();
}
private static void OnEntryWrittenAsync(object sender, EntryWrittenEventArgs e)
{
if (eventsToListen.Contains(e.Entry.InstanceId.ToString()))
{
Task.Factory.StartNew(() => writeToRemoteLog(e.Entry));
}
}
private static void writeToRemoteLog(EventLogEntry entry)
{
string logMessage = null;
if (EventLog.Exists("DCGroupEvents", "targetMachineName"))
{
try
{
var log = new EventLog("DCGroupEvents", "targetMachineName");
log.Source = "DCGroupEvents";
String strMessage = entry.Index.ToString();
log.WriteEntry(strMessage);
log.Close();
logMessage = entry.InstanceId.ToString() + "/" + entry.TimeWritten.ToString() + "/" + entry.Index.ToString() + " written to eventlog";
}
catch (Exception e)
{
logMessage = e.Message;
}
}
else
{
logMessage = "Log does not exist";
}
Console.WriteLine(logMessage);
logMessage = null;
}
}
如何每天避免多次下载所有符合标准的事件?
在此先感谢所有知道这一点的人,此刻我有些困惑。
答案 0 :(得分:0)
仅当上一次写入事件至少在六秒钟之前发生时,系统才对WriteEntry作出响应。这意味着即使发生了多个事件日志更改,您也只会在六秒钟的间隔内收到一个EntryWritten事件通知。如果您在两次调用WriteEntry之间插入足够长的睡眠间隔(大约10秒),则不太可能错过事件。但是,如果写入事件发生的频率更高,则可能要等到下一个时间间隔,才能收到事件通知。通常,错过的事件通知不会丢失,而是会延迟。
答案 1 :(得分:0)
虽然不是理想的解决方案,可以尝试并使用映射表通过实现字典来解决这个问题,其存储所述事件属性和事件的索引ID。创建一个将验证和更新映射表并返回布尔结果的方法。然后,而不是执行时的事件被触发的活性,通过调用ValidatedUpdate(PARAMS)并基于该结果来执行的活性进行验证。 ValidatedUpdate(params)方法检查1;如果事件是在当日的第二天写的;如果索引ID已经存在于映射表3;如果事件ID与您需要过滤的ID相同。
当这些条件匹配时,则仅将其确定为当天的“新”事件。然后将该条目添加到字典中,并且可以返回布尔结果以供将来跟踪。为了减少臃肿,定时器可通过刷新值来实现每天将要“干净”的映射表。像下面这样
private ConcurrentDictionary<int, DateTime> mappingTable;
private bool ValidateAndUpdate(int id, DateTime entry)
{
try
{
if(!mappingTable.ContainsKey(id) && entry.TimeStamp > DateTime.Today.Date)
{
mappingTable.TryAdd(id, entry);
return true;
}
else
{
return false;
}
}
catch(Exception exception)
{
//handle exception event
}
}
private void OnEntryWritten(object sender, EntryWrittenEventArgs e)
{
//preceding code here
if(ValidateAndUpdate(e.Entry.Index, entry) == true)
{
//perform operation
}
catch(Exception exception)
{
//handle exception event
}
}