C# 在远程机器上读取事件日志的最快方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/914446/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the Fastest way to read event log on remote machine?
提问by Kapil
I am working on an application which reads eventlogs(Application) from remote machines. I am making use of EventLog class in .net and then iterating on the Log entries but this is very slow. In some cases, some machines have 40000+ log entries and it takes hours to iterate through the entries. what is the best way to accomplish this task? Are there any other classes in .net which are faster or in any other technology?
我正在开发一个从远程机器读取事件日志(应用程序)的应用程序。我在 .net 中使用 EventLog 类,然后迭代日志条目,但这非常慢。在某些情况下,某些机器有 40000 多个日志条目,并且需要数小时才能遍历这些条目。完成这项任务的最佳方法是什么?.net 中是否还有其他更快的类或任何其他技术?
回答by crauscher
回答by Drahakar
Maybe that the remote computers could do a little bit of computing. So this way your server would only deal with relevant information. It would be a kind of cluster using the remote computer to do some light filtering and the server would the the analysis part.
也许远程计算机可以做一点计算。因此,这样您的服务器将只处理相关信息。这将是一种集群,使用远程计算机进行一些光过滤,服务器将进行分析部分。
回答by Mike Shepard
Have you tried using the remoting features in powershell 2.0? They allow you to execute cmdlets (like ones to read event logs) on remote machines and return the results (as objects, of course) to the calling session.
您是否尝试过使用 powershell 2.0 中的远程处理功能?它们允许您在远程计算机上执行 cmdlet(例如读取事件日志的 cmdlet)并将结果(当然作为对象)返回到调用会话。
回答by Peter
You could place a Program at those machines that save the log to file and sends it to your webapplication i think that would be alot faster as you can do the looping local but im not sure how to do it so i cant ive you any code :(
您可以在那些将日志保存到文件并将其发送到您的网络应用程序的机器上放置一个程序,我认为这会更快,因为您可以在本地进行循环,但我不知道该怎么做,所以我无法为您提供任何代码: (
回答by ChrisW
Man, I feel your pain. We had the exact same issue in our app.
伙计,我感觉到你的痛苦。我们在我们的应用程序中遇到了完全相同的问题。
Your solution has a branch depending on what server version you're running on and what server version your "target" machine is running on.
您的解决方案有一个分支,具体取决于您正在运行的服务器版本以及您的“目标”机器正在运行的服务器版本。
If you're both on Vista or Windows Server 2008, you're in luck. You should look at System.Diagnostics.Eventing.Reader.EventLogQuery
and System.Diagnostics.Eventing.Reader.EventLogReader
. These are new in .net 3.5.
如果您同时使用 Vista 或 Windows Server 2008,那么您很幸运。你应该看看System.Diagnostics.Eventing.Reader.EventLogQuery
和System.Diagnostics.Eventing.Reader.EventLogReader
。这些是 .net 3.5 中的新功能。
Basically, you can build a query in XML and ship it over to run on the remote computer. Maybe you're just searching for events of a specific type, or maybe just new events from a specific point in time. The search runs on the remote machine, and then you just get back the matching events. The new classes are much faster than the old .net 2.0 way, but again, they are only supported on Vista or Windows Server 2008.
基本上,您可以用 XML 构建查询并将其传送到远程计算机上运行。也许您只是在搜索特定类型的事件,或者只是特定时间点的新事件。搜索在远程机器上运行,然后您只需返回匹配的事件。新类比旧的 .net 2.0 方式快得多,但同样,它们仅在 Vista 或 Windows Server 2008 上受支持。
For our app when the target is NOT on Vista/Win2008, we downloaded the raw .evt file from the remote system, and then parsed the file using its binary format. There are several sources of data about the event log format for .evt files (pre-Vista), including link textand an article I recall on codeproject.com that had some c# code.
对于我们的应用程序,当目标不在 Vista/Win2008 上时,我们从远程系统下载原始 .evt 文件,然后使用其二进制格式解析该文件。有几个关于 .evt 文件(Vista 之前)的事件日志格式的数据来源,包括链接文本和我记得在 codeproject.com 上有一些 c# 代码的文章。
Vista and Windows Server 2008 machines use a new .evtx format that is a new format, so you can't use the same binary parsing approach across all versions. But the new EventLogQuery and EventLogReader classes are so fast that you won't have to. It's now perfectly speedy to just use the built-in classes.
Vista 和 Windows Server 2008 计算机使用新的 .evtx 格式,这是一种新格式,因此您不能在所有版本中使用相同的二进制解析方法。但是新的 EventLogQuery 和 EventLogReader 类非常快,您不必这样做。现在只使用内置类非常快。
回答by Silent Steve
Event Log Reader is horribly slow... too slow. WTF Microsoft?
事件日志阅读器非常慢……太慢了。WTF 微软?
Use LogParser 2.2 - Search for C# and LogParser on the Internet (or you can use the log parser commands from the command line). I don't want to duplicate the work already contributed by others.
使用 LogParser 2.2 - 在 Internet 上搜索 C# 和 LogParser(或者您可以从命令行使用日志解析器命令)。我不想重复别人已经贡献的工作。
I pull the log from the remote system by having the log exported as an EVTX file. I then copy the file from the remote system. This process is really quick - even with a network that spans the planet (I had issues with having the log exported to a network resource). Once you have it local, you can do your searches and processing.
我通过将日志导出为 EVTX 文件来从远程系统中提取日志。然后我从远程系统复制文件。这个过程真的很快——即使是一个跨越地球的网络(我在将日志导出到网络资源时遇到了问题)。一旦你把它放在本地,你就可以进行搜索和处理。
There are multiple reasons for having the EVTX - I won't get into the reasons why we do this.
拥有 EVTX 有多种原因——我不会深入探讨我们这样做的原因。
The following is a working example of the code to save a copy of the log as an EVTX: (Notes: "device" is the network host name or IP. "LogName" is the name of the log desired: "System", "Security", or "Application". outputPathOnRemoteSystem is the path on the remote computer, such as "c:\temp\%hostname%.%LogName%.%YYYYMMDD_HH.MM%.evtx".)
以下是将日志副本保存为 EVTX 的代码的工作示例:(注意:“设备”是网络主机名或 IP。“LogName”是所需日志的名称:“系统”、“ Security”或“Application”。outputPathOnRemoteSystem 是远程计算机上的路径,例如“c:\temp\%hostname%.%LogName%.%YYYYMMDD_HH.MM%.evtx”。)
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;
}
回答by j.zeddi
A good Explanation/Example can be found on MSDN.
可以在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]");
EventLogReader reader = new EventLogReader(query);
for (EventRecord eventInstance = reader.ReadEvent();
null != eventInstance;
eventInstance = reader.ReadEvent())
{
// Output or save your event data here.
}
When waiting 5-20 minutes with the old code this one does it in less than 10 seconds.
当使用旧代码等待 5-20 分钟时,此代码在 10 秒内完成。
回答by Michael Ushakov
回答by AtzeBK
Just had the same issue and want to share my solution. It makes a search through application, system and security eventlogs from 260 seconds (using EventLog) about a 100 times faster (using EventLogQuery). And this in a way where it is possible to check if the event message contains a pattern or any other check without the requirement of FormatDescription().
刚遇到同样的问题,想分享我的解决方案。它从 260 秒(使用 EventLog)开始搜索应用程序、系统和安全事件日志,大约快 100 倍(使用 EventLogQuery)。并且这种方式可以在不需要 FormatDescription() 的情况下检查事件消息是否包含模式或任何其他检查。
My trick is to use the same mechanism as PowerShells Get-WinEvent does and then pass it through the result check.
我的技巧是使用与 PowerShell 的 Get-WinEvent 相同的机制,然后通过结果检查传递它。
Here is my code to find all events within last 4 days where the event message contains a filter pattern.
这是我的代码,用于查找过去 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++;
}
}
}