How to get a list of all Windows Event Logs (Event Viewer Logs) with their hierarchy and friendly names in C#
See the question and my original answer on StackOverflowThis blog here: The EventSource NuGet package and support for the Windows Event Log (Channel Support) has a link to a rare EventSource User's Guide document that states this:
Do use the EventSourceAttribute’s Name property to provide a descriptive, qualified name for the ETW event provider represented by your event source. The default is the short name of your event source type, which can easily lead to collisions, as ETW provider names share one machine-wide namespace. An example of a good provider name “
<CompanyName>-<Product>-<Component>
”. Following this 3-element convention will ensure Event Viewer displays your event logs in a logical folder hierarchy:“Application and Services Logs/<CompanyName>/<Product>/<Component>
”.
Which tends to indicate the dashes are more a convention than a strict requirement (So I believe you can parse it by yourself). Note the blog is still open for comments.
As for names that don't match, there is an undocumented EvtIntGetClassicLogDisplayName function that can get you the name displayed in Event Viewer. Here is how to use it with a session and a log name:
static void Main(string[] args)
{
var session = new EventLogSession();
foreach (string name in session.GetLogNames())
{
Console.WriteLine(GetDisplayName(session, name));
}
}
And here is the support code (since it's undocumented, use at your own risks, plus it seems to be useful mostly for this 'OAlert' entry, so I'm not sure it's worth it):
public static string GetDisplayName(EventLogSession session, string logName)
{
var sb = new StringBuilder(512);
int bufferUsed = 0;
if (EvtIntGetClassicLogDisplayName(GetSessionHandle(session).DangerousGetHandle(), logName, 0, 0, sb.Capacity, sb, out bufferUsed))
return sb.ToString();
return logName;
}
private static SafeHandle GetSessionHandle(EventLogSession session)
{
return (SafeHandle)session.GetType().GetProperty("Handle", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(session);
}
[DllImport("wevtapi.dll", CharSet = CharSet.Unicode)]
private static extern bool EvtIntGetClassicLogDisplayName(IntPtr session, [MarshalAs(UnmanagedType.LPWStr)] string logName, int locale, int flags, int bufferSize, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder displayName, out int bufferUsed);