Search code examples
c#xsdevent-logxmlserializer

Reading event logs saved to XML format from .Net


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#?


Solution

  • 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.