我正在开发一个应用程序,从远程计算机读取事件日志(应用程序)。我使用 .net 中的 EventLog 类,并迭代日志条目,但这非常缓慢。在某些情况下,一些计算机有 40000+ 条日志条目,需要花费数小时才能迭代完所有条目。
如何以最佳方式完成此任务?是否有其他 .net 类或其他技术可以更快地实现?
我正在开发一个应用程序,从远程计算机读取事件日志(应用程序)。我使用 .net 中的 EventLog 类,并迭代日志条目,但这非常缓慢。在某些情况下,一些计算机有 40000+ 条日志条目,需要花费数小时才能迭代完所有条目。
如何以最佳方式完成此任务?是否有其他 .net 类或其他技术可以更快地实现?
兄弟,我感同身受。我们的应用程序也遇到了完全相同的问题。
你的解决方案分支取决于你正在运行的服务器版本和你的“目标”机器所运行的服务器版本。
如果您们两个都在Vista或Windows Server 2008上,那就很幸运了。你应该看一下System.Diagnostics.Eventing.Reader.EventLogQuery
和System.Diagnostics.Eventing.Reader.EventLogReader
。这些是.NET 3.5中新的功能。
基本上,你可以在XML中构建一个查询,并将其发送到远程计算机上运行。也许你只是在搜索特定类型的事件,或者仅仅是从特定时间点开始搜索新的事件。搜索在远程计算机上运行,然后你就可以得到匹配的事件。新的类比旧的.NET 2.0方式快得多,但它们仅在Vista或Windows Server 2008上受支持。
对于我们的应用程序,当目标不在Vista/Win2008上时,我们会从远程系统下载原始的.evt文件,然后使用其二进制格式解析文件。有几个关于.evt文件(Vista之前的文件)事件日志格式的数据来源,包括link text和我在codeproject.com上记得看到的一篇文章,其中有一些C#代码。
Vista和Windows Server 2008机器使用了一个新的.evtx格式,这是一种新格式,因此你不能在所有版本上使用相同的二进制解析方法。但新的EventLogQuery和EventLogReader类非常快,所以你不必这样做。现在只需要使用内置的类就可以轻松处理了。
一个好的解释/示例可以在MSDN上找到。
EventLogSession session = new EventLogSession(Environment.MachineName);
// [System/Level=2] filters out the errors
// Where "Log" is the log you want to get data from.
EventLogQuery query = new EventLogQuery("Log", PathType.LogName, "*[System/Level=2]");
query.Session = session;
EventLogReader reader = new EventLogReader(query);
for (EventRecord eventInstance = reader.ReadEvent();
null != eventInstance;
eventInstance = reader.ReadEvent())
{
// Output or save your event data here.
}
使用旧代码等待 5-20 分钟,而这个代码不到 10 秒就能完成。
query.Session = session
。 - OfirD static public bool DumpLog(string device, string LogName, string outputPathOnRemoteSystem, out string errMessage)
{
bool wasExported = false;
string errorMessage = "";
try
{
System.Diagnostics.Eventing.Reader.EventLogSession els = new System.Diagnostics.Eventing.Reader.EventLogSession(device);
els.ExportLogAndMessages(LogName, PathType.LogName, "*", outputPathOnRemoteSystem);
wasExported = true;
}
catch (UnauthorizedAccessException e)
{
errorMessage = "Unauthorized - Access Denied: " + e.Message;
}
catch (EventLogNotFoundException e)
{
errorMessage = "Event Log Not Found: " + e.Message;
}
catch (EventLogException e)
{
errorMessage = "Export Failed: " + e.Message + ", Log: " + LogName + ", Device: " + device;
}
errMessage = errorMessage;
return wasExported;
}
刚遇到同样的问题,想分享我的解决方案。使用EventLogQuery可以使应用程序、系统和安全事件日志的搜索速度快100倍,时间只需260秒(使用EventLog)。 而且这种方式可以检查事件消息是否包含模式或任何其他检查,而无需FormatDescription()。
我的技巧是使用与PowerShell Get-WinEvent相同的机制,然后通过结果检查。
以下是我的代码,用于查找最近4天内所有事件消息中包含筛选器模式的事件。
string[] eventLogSources = {"Application", "System", "Security"};
var messagePattern = "*Your Message Search Pattern*";
var timeStamp = DateTime.Now.AddDays(-4);
var matchingEvents = new List<EventRecord>();
foreach (var eventLogSource in eventLogSources)
{
var i = 0;
var query = string.Format("*[System[TimeCreated[@SystemTime >= '{0}']]]",
timeStamp.ToUniversalTime().ToString("o"));
var elq = new EventLogQuery(eventLogSource, PathType.LogName, query);
var elr = new EventLogReader(elq);
EventRecord entryEventRecord;
while ((entryEventRecord = elr.ReadEvent()) != null)
{
if ((entryEventRecord.Properties)
.FirstOrDefault(x => (x.Value.ToString()).Contains(messagePattern)) != null)
{
matchingEvents.Add(entryEventRecord);
i++;
}
}
}
你尝试过在PowerShell 2.0中使用远程功能吗?它们允许你在远程计算机上执行cmdlet(比如读取事件日志的cmdlet),并将结果(当然是作为对象)返回给调用会话。