如何在Windows中向EventLog添加多行EventData?

时间:2011-10-08 01:44:28

标签: c# event-log

我目前能够使用以下代码创建Windows事件日志:

    string sSource;
    string sLog;
    string sEvent;
    sSource = "Sample App";
    sLog = "Application";
    sEvent = "Sample Event";

    if (!EventLog.SourceExists(sSource))
        EventLog.CreateEventSource(sSource,sLog);

EventLog.WriteEntry(sSource, sEvent, EventLogEntryType.Warning, 11111);

这将在“应用程序日志”中创建一个日志。 我想在事件日志中为事件添加多行数据,以便在调试时我可以直接解析日志以解决问题。 此外,我查看了应用程序日志中的一些其他日志,它们似乎有一个二进制数据字段。我无法弄清楚如何编写这样的字段,因为上面的代码只添加了一个EventData字段。

6 个答案:

答案 0 :(得分:3)

一个班轮应该是这样的:

ng-repeat

此处应用程序是事件源,123是事件Id,0 = NONE是事件类别。您可能需要先检查事件源是否存在。

这就是事件的样子:

EventLog.WriteEvent("Application", new EventInstance(123, 0, EventLogEntryType.Information), new object[] { "Entry1" , "Entry2" });

答案 1 :(得分:2)

我尝试使用EventLog.WriteEntry()使用\ n \ t。但是我没有成功。 我找到了解决这个问题的方法。我们可以使用logger.WriteEvent()

//Object of eventinstance.

EventInstance eventInstance= new EventInstance(0, 0) {EntryType =       EventLogEntryType.Warning};
//Array of string.Event data node is generated based on the array size.

string [] eventLog = EventLogger.BuildEventLog("EventLogSamples.WriteEventSample2","test");

//Need to specify the source

EventLog log = new EventLog {Source = "source"};
log.WriteEvent(eventInstance, eventLog);

我能够成功编写多个eventData,如下所示

- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
  <Provider Name="test" /> 

  </System>
- <EventData>
  <Data>EventLogSamples.WriteEventSample2</Data> 
  <Data>test</Data> 
  </EventData>
  </Event>

如果您发现任何问题,请告诉我。 PK(Prathap Kudupu)

答案 2 :(得分:2)

如果您只想使用简单的<Data Name="param1">data</Data>结构,上述答案就可以了,但是如果您想使用更复杂的有效负载(例如,就像您遇到了蓝屏事件:

<Data Name="BugcheckCode">4522044</Data> 
<Data Name="BugcheckParameter1">0x74006e00650076</Data> 
<Data Name="BugcheckParameter2">0x61007400610044</Data> 
<Data Name="BugcheckParameter3">0x610044003c003e</Data> 
<Data Name="BugcheckParameter4">0x4e002000610074</Data> 
<Data Name="SleepInProgress">7143521</Data> 
<Data Name="PowerButtonTimestamp">18577494495789157</Data> 
<Data Name="BootAppStatus">6750325</Data> 
<Data Name="Checkpoint">99</Data> 
<Data Name="ConnectedStandbyInProgress">true</Data> 
<Data Name="SystemSleepTransitionsToOn">1795187456</Data> 
<Data Name="CsEntryScenarioInstanceId">0</Data> 
<Data Name="BugcheckInfoFromEFI">true</Data> 

我不认为可以使用EventLog.WriteEntry帮助程序来实现。我注意到您可以使用PowerShell执行此操作:

New-WinEvent -ProviderName Microsoft-Windows-Kernel-Power -Id $evtID -Version 5 -Payload "<EventData><Data Name=""BugcheckCode"">210</Data><Data Name=""BugcheckParameter1"">0xffffc080b5744760</Data><Data Name=""BugcheckParameter2"">0x2</Data><Data Name=""BugcheckParameter3"">0x0</Data><Data Name=""BugcheckParameter4"">0xfffff80261641530</Data><Data Name=""SleepInProgress"">0</Data><Data Name=""PowerButtonTimestamp"">0</Data><Data Name=""BootAppStatus"">0</Data><Data Name=""Checkpoint"">0</Data><Data Name=""ConnectedStandbyInProgress"">false</Data><Data Name=""SystemSleepTransitionsToOn"">0</Data><Data Name=""CsEntryScenarioInstanceId"">0</Data><Data Name=""BugcheckInfoFromEFI"">false</Data><Data Name=""CheckpointStatus"">0</Data></EventData>"

所以我挖出了它使用的dll并将代码反映出来。我最后得到了一个小帮助程序类,该类允许您传递所需的任何有效负载:

public class EventLogHelper
{
        /// <summary>
        /// Taken from the source code of Microsoft.PowerShell.Commands.NewWinEventCommand
        /// </summary>
        /// <param name="providerName">"Microsoft-Windows-Kernel-Power"</param>
        /// <param name="eventId">41</param>
        /// <param name="version">5</param>
        /// <param name="payLoad"></param>
        public static void AddEventToEventLog(string providerName, long eventId, int version, string payLoad = "")
        {
            using (ProviderMetadata providerMetaData = LoadProvider(providerName))
            {
                EventDescriptor eventDescriptor = LoadEventDescriptor(providerMetaData, eventId, Convert.ToByte(version));


                ProcessRecord(providerMetaData, eventDescriptor, payLoad);
            }
        }

        private static ProviderMetadata LoadProvider(string providerName)
        {
            using (EventLogSession eventLogSession = new EventLogSession())
            {
                IEnumerable<string> providers = eventLogSession.GetProviderNames().OrderBy(s => s);
                foreach (string providerName2 in providers)
                {
                    if (string.Equals(providerName2, providerName, StringComparison.OrdinalIgnoreCase))
                    {

                        return new ProviderMetadata(providerName2);

                    }
                }
            }

            throw new Exception("Failed to find Microsoft-Windows-Kernel-Power provider");
        }

        private static EventDescriptor LoadEventDescriptor(ProviderMetadata providerMetadata, long id, byte version)
        {

            EventMetadata eventMetadata = providerMetadata.Events.First(f => f.Id == id && f.Version == version);

            return CreateEventDescriptor(providerMetadata, eventMetadata);

        }

        private static EventDescriptor CreateEventDescriptor(ProviderMetadata providerMetaData, EventMetadata emd)
        {
            long num = 0L;
            foreach (EventKeyword keyword in emd.Keywords)
            {
                num |= keyword.Value;
            }
            byte b = 0;
            using (IEnumerator<EventLogLink> enumerator2 = providerMetaData.LogLinks.GetEnumerator())
            {
                while (enumerator2.MoveNext() && !string.Equals(enumerator2.Current.LogName, emd.LogLink.LogName, StringComparison.OrdinalIgnoreCase))
                {
                    b = (byte)(b + 1);
                }
            }

            int parsedId = (int)emd.Id;

            if (emd.Id > ushort.MaxValue)
                parsedId = (ushort)emd.Id;

            return new EventDescriptor(parsedId, emd.Version, b, (byte)emd.Level.Value, (byte)emd.Opcode.Value, emd.Task.Value, num);
        }

        private static void ProcessRecord(ProviderMetadata providerMetadata, EventDescriptor eventDescriptor, string payload)
        {
            using (EventProvider eventProvider = new EventProvider(providerMetadata.Id))
            {

                eventProvider.WriteEvent(ref eventDescriptor, payload);

            }
        }
}

这可以称为:

string payload = @"<EventData><Data Name=""BugcheckCode"">210</Data><Data Name=""BugcheckParameter1"">0xffffc080b5744760</Data><Data Name=""BugcheckParameter2"">0x2</Data><Data Name=""BugcheckParameter3"">0x0</Data><Data Name=""BugcheckParameter4"">0xfffff80261641530</Data><Data Name=""SleepInProgress"">0</Data><Data Name=""PowerButtonTimestamp"">0</Data><Data Name=""BootAppStatus"">0</Data><Data Name=""Checkpoint"">0</Data><Data Name=""ConnectedStandbyInProgress"">false</Data><Data Name=""SystemSleepTransitionsToOn"">0</Data><Data Name=""CsEntryScenarioInstanceId"">0</Data><Data Name=""BugcheckInfoFromEFI"">false</Data><Data Name=""CheckpointStatus"">0</Data></EventData>";
EventLogHelper.AddEventToEventLog("Microsoft-Windows-Kernel-Power", 41, 5, payload);

答案 3 :(得分:1)

如果您想添加更多行,您只需添加一个&#39;环境。新线&#39;

  [Extension()]
    [MethodImpl(MethodImplOptions.NoInlining)]
    public void WriteInfo(string info)
    {
        try
        {
            MethodBase callingMethod = new StackFrame(1, true).GetMethod();
            string typeCalling = callingMethod.DeclaringType.FullName;

            string baseStr = "TYPE: {0}{3} METHOD: {1}{3} DETAIL: {2}";
            baseStr = string.Format(baseStr, new object[] {
                                                        callingMethod,
                                                        typeCalling,
                                                        info,
                                                        Environment.NewLine
    });

            EventLog.WriteEntry("entryName", baseStr, EventLogEntryType.Information);
        }
        catch
        {
            Debugger.Break();

        }
    }

答案 4 :(得分:1)

我对Prathap Kudpu的答案感到有点困惑,所以我重写了它

{
    string sSource = "Application Name";
    string sLog = "Application";

    EventInstance eventInstance = new EventInstance(0, 0, EventLogEntryType.Error);

    List<string> sEvent = new List<string>();
    sEvent.Add("Message 1");
    sEvent.Add("Message 2");
    sEvent.Add("Message 3");

    // Check if Event Source was created (Possibly throw error if you are not running with high privilege)
    if (!EventLog.SourceExists(sSource))
        EventLog.CreateEventSource(sSource, sLog);            

    EventLog.WriteEvent(sSource, eventInstance, sEvent.ToArray());
}

基本上,您创建一个包含所需“行”或数据的字符串列表,创建一个EventInstance对象,然后编写一个事件而不是WriteEntry

结果:

<EventData>
  <Data>Message 1</Data> 
  <Data>Message 2</Data> 
  <Data>Message 3</Data> 
</EventData>

答案 5 :(得分:-1)

只需在邮件字符串中添加换行符即可记录多行文字。