Nigel Tunnicliffe
Nigel Tunnicliffe

Reputation: 131

XPath to select EventLog record where source contains string

I am writing an XPath query string to select records from the Windows Event Log where the Event source contains a particular string. I have a version which performs an exact match where the Path element of the query is

Path='Application'>*[System[Provider[@Name='MyApp']

This works fine, but I want to find all events where the source contains 'MyApp'. I have read various articles and I think it should be

Path='Application'>*[System[Provider[contains(@Name, 'MyApp']

but this fails with an 'Invalid Query' error.

Any idea what I am doing wrong?

Update:

I edited my query in line with the fix below and my full query string is now:

var Query = @"<QueryList><Query Id='0' Path='Application'>
                        <Select Path='Application'>*[System[Provider[contains(@Name, 'MyApp')] and (Level=2 or Level=3)]]</Select>
                        </Query></QueryList>";

var EventLogQuery = new EventLogQuery("Application", PathType.LogName, Query);

but this still fails. If I change the query to be

var Query = @"<QueryList><Query Id='0' Path='Application'>
                                <Select Path='Application'>*[System[Provider[@Name='MyApp'] and (Level=2 or Level=3)]]</Select>
                                </Query></QueryList>";

it all works.

Does the EventLogQuery support 'contains'. This article How to select for content contains substring in Windows Event Viewer using XPath 1.0? suggests it does not.

Upvotes: 1

Views: 116

Answers (2)

kjhughes
kjhughes

Reputation: 111716

  1. Your posted XPath is missing a closing ) for contains() and closing predicate ] for several levels:

    *[System[Provider[contains(@Name, 'MyApp']
    

    should be

    *[System[Provider[contains(@Name, 'MyApp')]]]
    
  2. More conventionally, for a top-level Event element this would be written

    /Event[System/Provider[contains(@Name, 'MyApp')]]
    
  3. Take into account the namespaces typically involved. Given the following sample Windows Event Log XML,

    <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
      <System>
        <Provider Name="Microsoft-Windows-Security-Auditing" 
                  Guid="{12345678-1234-1234-1234-123456789012}" />
      </System>
    </Event>
    

    by declaring a namespace prefix,

    e = "http://schemas.microsoft.com/win/2004/08/events/event"
    

    and using it in your XPath,

    /e:Event[e:System/e:Provider[contains(@Name, 'MyApp')]]
    

    See How does XPath deal with XML namespaces? for how to declare and use (or defeat if necessary) namespaces in XPath.

  4. The above assumes that you're using a full, compliant XPath processor/library. Apparently Windows Event Log is not (thanks to the link provided by @JamesCockayne, +1):

    Windows Event Log supports a subset of XPath 1.0. For details on the limitations, see XPath 1.0 limitations.

    In general, it's better to use a fully compliant XPath processor/library.

Upvotes: 1

James Cockayne
James Cockayne

Reputation: 138

I think the issue is that the contains function is missing a closing parentheses. I also think we are missing some closing square braces. I'm not sure how your first example works.

Try *[System[Provider[contains(@Name, 'MyApp')]]]

This guide seems to have many good examples that you should be able to modify to meet your needs https://learn.microsoft.com/en-us/windows/win32/wes/consuming-events

Upvotes: 1

Related Questions