{"id":1247,"date":"2014-06-05T00:01:00","date_gmt":"2014-06-05T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2014\/06\/05\/using-powershell-to-parse-system-log-for-windows-updates\/"},"modified":"2014-06-05T00:01:00","modified_gmt":"2014-06-05T00:01:00","slug":"using-powershell-to-parse-system-log-for-windows-updates","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/using-powershell-to-parse-system-log-for-windows-updates\/","title":{"rendered":"Using PowerShell to Parse System Log for Windows Updates"},"content":{"rendered":"<p><b>Summary<\/b>: Learn how to use XML and Windows PowerShell to parse the Windows system event log for Windows updates.<\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, is here. Sometimes I come up with a solution, and then I go looking for a problem to fix. Not often, but sometimes. This is usually the result of playing around with Windows PowerShell on the weekend, and trying different things until I come up with something I think is cool.<\/p>\n<p>This is not one of those occasions. In fact, today&rsquo;s blog post is pretty important for several reasons. The first reason is that I show how to use an XML filter to retrieve Windows event log entries that are written by the Windows Update. Not too big of a deal because I did that yesterday&mdash;at least, I used XML to filter the event log. In and of itself, this is a very valuable skill to develop because it generates huge performance increases.<\/p>\n<p>The second reason this post is important is because I also show you how to use XML to retrieve a specific node from the event data portion of the event log entry. This is huge, because more event log entries are storing more information in the message portion. It is well-formed XML. Most of the stuff you see floating around on the Internet takes a long way around, and it ends up doing all sorts of contorted stuff. My approach is relatively straightforward.<\/p>\n<h2>First the query<\/h2>\n<p>Obviously the first thing to do is to develop the query. I am using a <b>FilterXML<\/b> query to retrieve Windows Update events from the system event log.<\/p>\n<p style=\"margin-left:30px\"><b>Note&nbsp;<\/b> For more information about this technique, refer to <a href=\"https:\/\/devblogs.microsoft.com\/scripting\/data-mine-the-windows-event-log-by-using-powershell-and-xml\/\" target=\"_blank\">Data Mine the Windows Event Log by Using PowerShell and XML<\/a>.<\/p>\n<p>I did not have to do too much to this query. In fact, it was as simple as clicking the boxes in the Event Viewer, and then switching to XML. The results of this operation are shown here:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-5-14-01.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-5-14-01.png\" alt=\"Image of menu\" width=\"400\" height=\"400\" title=\"Image of menu\" \/><\/a><\/p>\n<p>I store the query in a here string. Here is my 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;System&quot;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; &lt;Select Path=&quot;System&quot;&gt;*[System[Provider<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [@Name=&#039;Microsoft-Windows-WindowsUpdateClient&#039;]<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and (Level=4 or Level=0) and Task = 1<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and (band(Keywords,8200))]]&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>Now, I need to use the <b>&ndash;FilterXML<\/b> parameter of the <b>Get-WinEvent<\/b> cmdlet to perform the actual query. I will also store the resulting events in a variable I call <b>$systemEvents<\/b>. This is shown here:<\/p>\n<p style=\"margin-left:30px\">$systemEvents = Get-WinEvent -FilterXml $query&nbsp;<\/p>\n<h2>Search the matching events<\/h2>\n<p>I now need to search all of the matching Windows Update events that I stored in the <b>$systemEvents<\/b> variable and look for the name of the updates. To do this, I use a <b>Foreach<\/b> loop to walk through the events. I store the time the event was created, and I convert the event log entry to XML by calling the <b>toxml<\/b> method. This is shown here:<\/p>\n<p style=\"margin-left:30px\">$systemEvents = Get-WinEvent -FilterXml $query<\/p>\n<p style=\"margin-left:30px\">Foreach($event in $systemEvents)<\/p>\n<p style=\"margin-left:30px\">{<\/p>\n<p style=\"margin-left:30px\">&nbsp;$tc = $event.TimeCreated<\/p>\n<p style=\"margin-left:30px\">&nbsp;$xml = [xml]$event.toxml()<\/p>\n<p>When I have an XML document, I call the <b>SelectSingleNode<\/b> method, and I retrieve the <b>@Name=&rsquo;updateTitle&rsquo;<\/b> node. When trying to find out what I need to use, I refer to the XML view of the event log entry in the Event Viewer as shown here:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-5-14-02.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-5-14-02.png\" alt=\"Image of menu\" title=\"Image of menu\" \/><\/a><\/p>\n<p>I then pipe the node to the <b>Select-Object<\/b> cmdlet, and I expand the <b>#text<\/b> property. I found this whilst playing around with <b>Get-Member<\/b> and exploring the returned objects from the various commands. I store the update title (from the <b>#text<\/b> property) in a variable I call <b>$ud<\/b>.<\/p>\n<p style=\"margin-left:30px\"><b>Note<\/b>&nbsp;&nbsp;Because the <b>#text <\/b>property begins with a pound sign, I have to put quotation marks around it; otherwise, Windows PowerShell views it as the comment character. I should also say that using the grave accent character ( <b>`<\/b> ) does not work for this.<\/p>\n<p>Now, I want to return an object, so I use the <b>New-Object<\/b> cmdlet to create an object that contains the time stamp and the name of the update. This section is shown here:<\/p>\n<p style=\"margin-left:30px\">$ud = $xml.SelectSingleNode(&quot;\/\/*[@Name=&#039;updateTitle&#039;]&quot;) |<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; Select -ExpandProperty &#039;#text&#039;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; New-Object -TypeName psobject -Property @{&quot;Date&quot;=$tc;&quot;Update&quot;=$ud}<\/p>\n<p style=\"margin-left:30px\">}<\/p>\n<p>When I run the script, the following output appears:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-5-14-03.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-6-5-14-03.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>The complete script is shown here:<\/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;System&quot;&gt;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; &lt;Select Path=&quot;System&quot;&gt;*[System[Provider<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [@Name=&#039;Microsoft-Windows-WindowsUpdateClient&#039;]<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and (Level=4 or Level=0) and Task = 1<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and (band(Keywords,8200))]]&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>&nbsp;<\/p>\n<p style=\"margin-left:30px\">$systemEvents = Get-WinEvent -FilterXml $query<\/p>\n<p style=\"margin-left:30px\">Foreach($event in $systemEvents)<\/p>\n<p style=\"margin-left:30px\">{<\/p>\n<p style=\"margin-left:30px\">&nbsp;$tc = $event.TimeCreated<\/p>\n<p style=\"margin-left:30px\">&nbsp;$xml = [xml]$event.toxml()<\/p>\n<p style=\"margin-left:30px\">&nbsp;$ud = $xml.SelectSingleNode(&quot;\/\/*[@Name=&#039;updateTitle&#039;]&quot;) |<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; Select -ExpandProperty &#039;#text&#039;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp; New-Object -TypeName psobject -Property @{&quot;Date&quot;=$tc;&quot;Update&quot;=$ud}<\/p>\n<p style=\"margin-left:30px\">}<\/p>\n<p>That is all there is to using XML to return event log data from a single node. Event Log Week will continue tomorrow when I will talk about some really 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: Learn how to use XML and Windows PowerShell to parse the Windows system event log for Windows updates. Microsoft Scripting Guy, Ed Wilson, is here. Sometimes I come up with a solution, and then I go looking for a problem to fix. Not often, but sometimes. This is usually the result of playing around [&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,42,3,4,45,165],"class_list":["post-1247","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-event-logs","tag-events-and-monitoring","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell","tag-xml"],"acf":[],"blog_post_summary":"<p>Summary: Learn how to use XML and Windows PowerShell to parse the Windows system event log for Windows updates. Microsoft Scripting Guy, Ed Wilson, is here. Sometimes I come up with a solution, and then I go looking for a problem to fix. Not often, but sometimes. This is usually the result of playing around [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/1247","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=1247"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/1247\/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=1247"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=1247"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=1247"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}