I'm trying to read an event log saved as an XML file from .Net / C#, the event log xml format looks (approximately) like this:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Events>
<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'>...</Event>
<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'>...</Event>
</Events>
Where the ...
bit is a relatively complex series of types defined in a schema file event.xsd.
My plan was to use XSD.exe to generate a C# wrapper type for reading this event log XML from this schema file and then deserialise the XML using the XmlSerializer
class, like so:
using (FileStream stream = File.OpenRead(filename))
{
XmlSerializer serialiser = new XmlSerializer(typeof(Events));
return (Events)serialiser.Deserialize(stream);
}
The trouble is that the schema file doesn't contain a definition for the Events
element (because its not in the schema), and so the above doesn't compile as there is no Events
type.
I've tried a couple of variations, including using the type EventType[]
instead of Events
(which resulted in the exception " was not expected."). I also attempting to craft my own C# container Events
type:
public class Events
{
[XmlElement]
public EventType[] Items
{
get;
set;
}
}
However the above simply results in the Items
array being null.
How can I read Events Logs saved to XML format from C#?
So I managed this by using the following class:
[Serializable]
[XmlType(AnonymousType = true)]
[XmlRoot(Namespace = "", IsNullable = false)]
public class Events
{
[XmlElement("Event", Namespace = "http://schemas.microsoft.com/win/2004/08/events/event")]
public EventType[] Items
{
get;
set;
}
}
I'm not entirely certain what it is that made this work where previously it failed (I suspect its the Namespace
property), however I found this out by using xsd.exe to generate a schema from a saved event log file and and then again to generate C# classes from that file, like so:
xsd /c eventlog.xml
xsd /c eventlog.xsd eventlog_app1.xsd
(Because it writes two xsd files you need to name both of them on the command line). I then looked at the resulting C# and compared / experimented until it worked.