How to add multiple lines of EventData to an EventLog in Windows?
I am able to currently create a Windows Event Log using the following code:
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);
This creates a log in the Application Log. I want to add more than one line of data to the event in the event log so that while debugging I can parse the log directly for the problems. Also, I looked at some of the other logs in the Application logs and they seem to have a binary data field in them. I was not able to figure out as to how to write such a field because the above piece of code only adds an EventD开发者_如何学运维ata field.
One liner should be like this:
EventLog.WriteEvent("Application", new EventInstance(123, 0, EventLogEntryType.Information), new object[] { "Entry1" , "Entry2" });
Here Application is event source, 123 is the event Id and 0 = NONE is event category. You may need to check the existence of the event source first.
This is how the event looks like:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Application" />
<EventID Qualifiers="0">1001</EventID>
<Level>4</Level>
<Task>0</Task>
<Keywords>0x80000000000000</Keywords>
<TimeCreated SystemTime="2015-07-12T21:26:07.000000000Z" />
<EventRecordID>86554</EventRecordID>
<Channel>Application</Channel>
<Computer>YOUR_COMPUTER</Computer>
<Security />
</System>
<EventData>
<Data>Entry1</Data>
<Data>Entry2</Data>
</EventData>
</Event>
I got a little confused about Prathap Kudpu's answer, so I rewrote it
{
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());
}
Basically, You create a list of string with the "Lines" or data you Want, create an EventInstance object, and Write an Event instead of WriteEntry
Result:
<EventData>
<Data>Message 1</Data>
<Data>Message 2</Data>
<Data>Message 3</Data>
</EventData>
The above answers are fine if you just want a simple <Data Name="param1">data</Data>
structure but it falls down if you want a more complex payload, e.g. like you get in a bluescreen event:
<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>
I don't believe this is possible using the EventLog.WriteEntry
helper. I noticed you can do this using PowerShell though:
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>"
So I dug out the dll that this uses and reflected the code out. I ended up with a little helper class that allows you to pass whatever payload you require:
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);
}
}
}
this can then be called:
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);
If you want to add more lines you can simply add an 'Enviroment.NewLine'
[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();
}
}
I tried using \n \t using EventLog.WriteEntry(). However I was not successful. I found a solution for this problem. We can use 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);
I was able to successfully write multiple eventData as shown below
- <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>
Please let me know if you find any issues. PK (Prathap Kudupu)
Simply put line break characters in your message string to log multiple lines of text.
精彩评论