{"id":1256,"date":"2014-06-04T00:01:00","date_gmt":"2014-06-04T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2014\/06\/04\/data-mine-the-windows-event-log-by-using-powershell-and-xml\/"},"modified":"2014-06-04T00:01:00","modified_gmt":"2014-06-04T00:01:00","slug":"data-mine-the-windows-event-log-by-using-powershell-and-xml","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/data-mine-the-windows-event-log-by-using-powershell-and-xml\/","title":{"rendered":"Data Mine the Windows Event Log by Using PowerShell and XML"},"content":{"rendered":"<p><b>Summary<\/b>: Microsoft Scripting Guy, Ed Wilson, talks about using <b>Get-WinEvent<\/b> in Windows PowerShell with <b>FilterXML<\/b> to parse event logs.<\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, is here. Today I am sipping a cup of English Breakfast tea. In my pot, I decided to add a bit of spearmint, peppermint, licorice root, lemon peel, orange peel, and lime peel to the tea. The result is a very refreshing cup of tea with a little added zing.<\/p>\n<h2>XML adds zing to event log queries<\/h2>\n<p>The other day when I opened the event log on my laptop, I noticed all the red stop signs, and I thought, &quot;Dude, I really need to investigate this.&quot;<\/p>\n<p>I decided to look at the application hangs. Although I can use the Event Viewer to filter for application hang, errors, and event ID 1002, that is as far as I can go by default. To see what application is hanging, I need to go into the message details box. This is a manual process and it is shown here:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-4-14-01.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-4-14-01.png\" alt=\"Image of menu\" title=\"Image of menu\" \/><\/a><\/p>\n<p>It is possible to improve this situation, and to filter only on a specific application. This is because the data is stored in the <strong>Event Data<\/strong> portion of the message. This section appears when I select <b>XML View<\/b> from the <b>Details<\/b> tab, as shown here:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-4-14-02.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-4-14-02.png\" alt=\"Image of menu\" title=\"Image of menu\" \/><\/a><\/p>\n<p>I can use this information to create a custom XML query by clicking <b>Filter Current Log<\/b>, clicking <b>XML<\/b>, and then clicking the <b>Edit query manually <\/b>check box. This is shown here:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-4-14-03.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-4-14-03.png\" alt=\"Image of menu\" title=\"Image of menu\" \/><\/a><\/p>\n<p>In fact, this process outlines my process for creating a custom XML filter to filter the event log. I select as much as I need by using the graphical tools, then I edit the XML query manually in the dialog box. The advantage is that if I do not get the query correct, it does not display any records, it displays the incorrect records, or it tells me my query is invalid. At least that is what happens to me.<\/p>\n<p>But I do not directly edit the query in the dialog box because if I get it wrong the first time, I have messed up my query. So I copy the autogenerated XML filter and paste it for safe keeping in a blank Notepad. I then edit the query. If I mess it up, I simple return to Notepad, retrieve my previous query, and start over. Simple.<\/p>\n<h2>Looking for instances of LYNC hangs<\/h2>\n<p>When I was rummaging around in the Event Viewer, I noticed that several of the hangs were caused by Lync.exe. So, I thought I would create a custom query to look for those instances. To do this, I need to get into the <strong>Event Data<\/strong> node and look for <strong>Lync<\/strong>.<\/p>\n<p>After I create a generic XML query by using the GUI tools, I copy the query, and turn it into a here string. Here is the basic query:<\/p>\n<p style=\"margin-left:30px\">&lt;QueryList&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&lt;Query Id=&quot;0&quot; Path=&quot;Application&quot;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; &lt;Select Path=&quot;Application&quot;&gt;*[System[Provider[@Name=&#039;Application Hang&#039;] and (Level=2) and (EventID=1002)]] &lt;\/Select&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp; &lt;\/Query&gt;<\/p>\n<p style=\"margin-left:30px\">&lt;\/QueryList&gt;<\/p>\n<p>To make it a here string, I add <b>@&rdquo; <\/b>and <b>&ldquo;@ <\/b>around the string, and I assign it to a variable. Now I need to access <b>EventData<\/b> and the first data that is equal to <b>Lync.exe<\/b>. I add it after <b>EventID=1002)]]<\/b> by using and to bring them together. Here is the completed query.<\/p>\n<p style=\"margin-left:30px\">$query = @&quot;<\/p>\n<p style=\"margin-left:30px\">&lt;QueryList&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp; &lt;Query Id=&quot;0&quot; Path=&quot;Application&quot;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; &lt;Select Path=&quot;Application&quot;&gt;*[System[Provider[@Name=&#039;Application Hang&#039;]<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; and (Level=2) and (EventID=1002)]]<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; and *[EventData[Data=&#039;lync.exe&#039;]]&lt;\/Select&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp; &lt;\/Query&gt;<\/p>\n<p style=\"margin-left:30px\">&lt;\/QueryList&gt;<\/p>\n<p style=\"margin-left:30px\">&quot;@<\/p>\n<p>To run it, all I do is call the <b>Get-WinEvent<\/b> and pass it to the <b>$query<\/b> parameter as a value for <b>&ndash;FilterXML<\/b>. This is shown here:<\/p>\n<p style=\"margin-left:30px\">Get-WinEvent -FilterXml $query&nbsp;<\/p>\n<p>The command and the results are shown in the following image:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-4-14-04.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-4-14-04.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<h2>Without using XML<\/h2>\n<p>Without using XML, someone may come up with a command something like the following:<\/p>\n<p style=\"margin-left:30px\">Get-WinEvent -LogName application |<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; where { $_.providername -eq &#039;application hang&#039; -and<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; $_.level -eq 2 -and<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; $_.ID -eq 1002 -and<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; $_.message -match &#039;lync.exe&#039;}<\/p>\n<p>It works, and it gets the job done. But what about the results?<\/p>\n<p>Although the command seems to work pretty well, I will use <b>Measure-Command<\/b> to see how well. To do this, I add the command to a script block for <b>Measure-Command<\/b>. Here is what it looks like:<\/p>\n<p style=\"margin-left:30px\">Measure-Command {Get-WinEvent -LogName application |<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; where { $_.providername -eq &#039;application hang&#039; -and<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; $_.level -eq 2 -and<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; $_.ID -eq 1002 -and<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; $_.message -match &#039;lync.exe&#039;} }<\/p>\n<p>The results? It takes 10.16 seconds as shown here:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-4-14-05.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-4-14-05.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>And now for the XML query&#8230;<\/p>\n<p style=\"margin-left:30px\">$query = @&quot;<\/p>\n<p style=\"margin-left:30px\">&lt;QueryList&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp; &lt;Query Id=&quot;0&quot; Path=&quot;Application&quot;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; &lt;Select Path=&quot;Application&quot;&gt;*[System[Provider[@Name=&#039;Application Hang&#039;]<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; and (Level=2) and (EventID=1002)]]<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; and *[EventData[Data=&#039;lync.exe&#039;]]&lt;\/Select&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp; &lt;\/Query&gt;<\/p>\n<p style=\"margin-left:30px\">&lt;\/QueryList&gt;<\/p>\n<p style=\"margin-left:30px\">&quot;@<\/p>\n<p style=\"margin-left:30px\">Measure-Command {Get-WinEvent -FilterXml $query }<\/p>\n<p>The results take a mere 0.07 second. This is an amazing speed increase. Here is an image of the script and the output:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-4-14-06.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-4-14-06.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Although this is a great performance, and it makes me happy on my laptop, suppose I was trying to run the command against a thousand computers. That ten seconds stretches into over two and a half hours. I spent less than five minutes making the query. So five minutes to save ten seconds is not a great investment. But five minutes dev time to save over two and a half hours is a great ROI.<\/p>\n<p>Spend a little time to work out the syntax for XML filters by using <b>Get-WinEvent<\/b>. This is an area where a bit of investment in learning will pay off handsomely in the future.<\/p>\n<p>That is all there is to using <b>Get-WinEvent<\/b> and an XML filter to parse the event log message data. Event Log Week will continue tomorrow when I will talk about more cool stuff.<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Get-WinEvent in Windows PowerShell with FilterXML to parse event logs. Microsoft Scripting Guy, Ed Wilson, is here. Today I am sipping a cup of English Breakfast tea. In my pot, I decided to add a bit of spearmint, peppermint, licorice root, lemon peel, orange peel, and [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[97,98,3,4,45,165],"class_list":["post-1256","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-event-logs","tag-logs-and-monitoring","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell","tag-xml"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Get-WinEvent in Windows PowerShell with FilterXML to parse event logs. Microsoft Scripting Guy, Ed Wilson, is here. Today I am sipping a cup of English Breakfast tea. In my pot, I decided to add a bit of spearmint, peppermint, licorice root, lemon peel, orange peel, and [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/1256","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=1256"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/1256\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=1256"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=1256"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=1256"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}