{"id":3234,"date":"2013-07-15T00:01:00","date_gmt":"2013-07-15T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2013\/07\/15\/use-powershell-and-a-filter-hash-table-to-speed-boot-trace\/"},"modified":"2013-07-15T00:01:00","modified_gmt":"2013-07-15T00:01:00","slug":"use-powershell-and-a-filter-hash-table-to-speed-boot-trace","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/use-powershell-and-a-filter-hash-table-to-speed-boot-trace\/","title":{"rendered":"Use PowerShell and a Filter Hash Table to Speed Boot Trace"},"content":{"rendered":"<p><strong style=\"font-size: 12px\">Summary<\/strong><span style=\"font-size: 12px\">: Microsoft Scripting Guy, Ed Wilson, talks about using a filter hash table with Windows PowerShell to speed up boot trace parsing.<\/span><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" alt=\"Hey, Scripting Guy! Question\" \/>&nbsp;Hey, Scripting Guy! I don&rsquo;t get it. You wrote a script yesterday, and said that the performance was bad. You suggested that you could improve the performance, but then you did not do anything about it. Why? Is it that the technique is too hard and you want to avoid work? This is disheartening to know if it is true. How about you throw us a bone so we can feed that dog of a script you wrote.<\/p>\n<p>&mdash;AB<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" alt=\"Hey, Scripting Guy! Answer\" \/>&nbsp;Hello AB,<\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, is here. Well, this morning I am sipping a cup of Darjeeling tea with a bit of lemon grass, crushed cinnamon stick, and a half spoonful of spearmint. The spearmint heightens the flavor, without overpowering it. The effect is quite soothing.<\/p>\n<p>AB, I am sorry you feel like I am sloughing off by not improving the performance of my previous script. It worked for me, and that was my primary concern. In addition, I have written quite a bit about improving the performance of event trace queries. The best post is <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2011\/03\/08\/how-to-improve-the-performance-of-a-powershell-event-log-query.aspx\" target=\"_blank\">How to Improve the Performance of a PowerShell Event Log Query<\/a>. To test the efficacy of my changes, I use the Test-TwoScripts.ps1 script that I talked about in <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2009\/07\/23\/hey-scripting-guy-how-can-i-test-the-efficacy-of-my-script-modifications.aspx\" target=\"_blank\">How Can I Test the Efficacy of My Script Modifications?<\/a><\/p>\n<p style=\"padding-left: 30px\"><strong>Note<\/strong>&nbsp;&nbsp;This post is a continuation of <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2013\/07\/14\/weekend-scripter-use-powershell-to-get-boot-up-trace-events.aspx\" target=\"_blank\">Use PowerShell to Get Boot-Up Trace Events<\/a>.<\/p>\n<h2>Using the FilterHashTable parameter<\/h2>\n<p>Sometimes, making a small change results in huge time savings. This script is an example. Using the <strong>FilterHashTable<\/strong><em> <\/em>parameter is nearly always a good idea when it comes to filtering via the <strong>Get-WinEvent<\/strong> cmdlet. The key is a hash table&mdash;not surprising really. The hash table is used to filter&mdash;once again, no surprise.<\/p>\n<p>A hash table has the &ldquo;key = value&rdquo; type of syntax. Therefore, the only thing that needs to be clarified is what can I use for a key? Luckily, these are well documented in the online Help for <a href=\"http:\/\/technet.microsoft.com\/library\/hh849682.aspx\">Get-WinEvent<\/a>. Key pair values for the <strong>FilterHashTable<\/strong><em> <\/em>parameter need to be one of the following:<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"223\">\n<p><strong>&nbsp; &nbsp; Key<\/strong><\/p>\n<\/td>\n<td valign=\"top\" width=\"216\">\n<p><strong>&nbsp; &nbsp; Value Data Type<\/strong><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"223\">\n<p>&nbsp;&nbsp;&nbsp; &nbsp;LogName<\/p>\n<\/td>\n<td valign=\"top\" width=\"216\">\n<p>&nbsp;&nbsp;&nbsp; &lt;String[]&gt;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"223\">\n<p>&nbsp;&nbsp;&nbsp; ProviderName<\/p>\n<\/td>\n<td valign=\"top\" width=\"216\">\n<p>&nbsp;&nbsp;&nbsp; &lt;String[]&gt;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"223\">\n<p>&nbsp;&nbsp;&nbsp; Path<\/p>\n<\/td>\n<td valign=\"top\" width=\"216\">\n<p>&nbsp;&nbsp;&nbsp; &lt;String[]&gt;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"223\">\n<p>&nbsp;&nbsp;&nbsp; Keywords<\/p>\n<\/td>\n<td valign=\"top\" width=\"216\">\n<p>&nbsp;&nbsp;&nbsp; &lt;Long[]&gt;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"223\">\n<p>&nbsp;&nbsp;&nbsp; ID<\/p>\n<\/td>\n<td valign=\"top\" width=\"216\">\n<p>&nbsp;&nbsp;&nbsp; &lt;Int32[]&gt;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"223\">\n<p>&nbsp;&nbsp;&nbsp; Level<\/p>\n<\/td>\n<td valign=\"top\" width=\"216\">\n<p>&nbsp;&nbsp;&nbsp; &lt;Int32[]&gt;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"223\">\n<p>&nbsp;&nbsp;&nbsp; StartTime<\/p>\n<\/td>\n<td valign=\"top\" width=\"216\">\n<p>&nbsp;&nbsp;&nbsp; &lt;DateTime&gt;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"223\">\n<p>&nbsp;&nbsp;&nbsp; EndTime<\/p>\n<\/td>\n<td valign=\"top\" width=\"216\">\n<p>&nbsp;&nbsp;&nbsp; &lt;DataTime&gt;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"223\">\n<p>&nbsp;&nbsp;&nbsp; UserID<\/p>\n<\/td>\n<td valign=\"top\" width=\"216\">\n<p>&nbsp;&nbsp;&nbsp; &lt;SID&gt;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"223\">\n<p>&nbsp;&nbsp;&nbsp; Data<\/p>\n<\/td>\n<td valign=\"top\" width=\"216\">\n<p>&nbsp;&nbsp;&nbsp; &lt;String[]&gt;<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"223\">\n<p>&nbsp;&nbsp;&nbsp; *<\/p>\n<\/td>\n<td valign=\"top\" width=\"216\">\n<p>&nbsp;&nbsp;&nbsp; &lt;String[]&gt;<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Using FilterHashTable for a filter<\/h2>\n<p><span style=\"font-size: 12px\">The first thing to keep in mind when using the <\/span><strong style=\"font-size: 12px\">FilterHashTable<\/strong><span style=\"font-size: 12px\"> parameter for a filter is that when you use it, you must include the name of the log. This is because the parameter set that contains <\/span><strong style=\"font-size: 12px\">FilterHashTable<\/strong><span style=\"font-size: 12px\"> does not also include <\/span><strong style=\"font-size: 12px\">LogName<\/strong><span style=\"font-size: 12px\">. The parameter set that includes <\/span><strong style=\"font-size: 12px\">LogName<\/strong><span style=\"font-size: 12px\"> does not include the <\/span><strong style=\"font-size: 12px\">FilterHashTable<\/strong><span style=\"font-size: 12px\"> parameter. These sets are shown here:<\/span><\/p>\n<p style=\"padding-left: 30px\"><strong>LogName<\/strong>:<\/p>\n<p style=\"padding-left: 30px\">Get-WinEvent [[-LogName] &lt;String[]&gt;] [-ComputerName &lt;String&gt;] [-Credential<\/p>\n<p style=\"padding-left: 30px\">&lt;PSCredential&gt;] [-FilterXPath &lt;String&gt;] [-Force [&lt;SwitchParameter&gt;]]<\/p>\n<p style=\"padding-left: 30px\">[-MaxEvents &lt;Int64&gt;] [-Oldest [&lt;SwitchParameter&gt;]] [&lt;CommonParameters&gt;]<\/p>\n<p style=\"padding-left: 30px\"><strong style=\"font-size: 12px\">FilterHashTable<\/strong><span style=\"font-size: 12px\">:<\/span><\/p>\n<p style=\"padding-left: 30px\">Get-WinEvent [-FilterHashtable] &lt;Hashtable[]&gt; [-ComputerName &lt;String&gt;]<\/p>\n<p style=\"padding-left: 30px\">[-Credential &lt;PSCredential&gt;] [-Force [&lt;SwitchParameter&gt;]] [-MaxEvents &lt;Int64&gt;]<\/p>\n<p style=\"padding-left: 30px\">[-Oldest [&lt;SwitchParameter&gt;]] [&lt;CommonParameters&gt;]<\/p>\n<p><span style=\"font-size: 12px\">So by using the previous table, I can easily modify the <\/span><strong style=\"font-size: 12px\">Foreach<\/strong><span style=\"font-size: 12px\"> portion of my script. Here is the original script:<\/span><\/p>\n<p style=\"padding-left: 30px\">Get-WinEvent -LogName $log.Logname -ea 0 |<\/p>\n<p style=\"padding-left: 30px\">&nbsp; where {$_.timecreated -gt $bootTime -and $_.timecreated -lt $bootTime.AddMinutes(5)}<\/p>\n<p>Here is the modified script:<\/p>\n<p style=\"padding-left: 30px\">Get-WinEvent -ea 0 -filterHashTable @{<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; LogName = $log.Logname;<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; StartTime = $bootTime;<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; EndTime = $bootTime.AddMinutes(5)}<\/p>\n<p>Not only does the script run a lot faster, but the <strong>FilterHashTable<\/strong> script is easier to read. Here is the complete, revised script:<\/p>\n<p style=\"padding-left: 30px\">$bootTime = (Get-CimInstance win32_Operatingsystem).lastbootuptime<\/p>\n<p style=\"padding-left: 30px\">&#8220;Boot time is $($bootTime)&#8221;<\/p>\n<p style=\"padding-left: 30px\">Foreach($log in Get-WinEvent -ListLog *)<\/p>\n<p style=\"padding-left: 30px\">&nbsp;{<\/p>\n<p style=\"padding-left: 30px\">&nbsp; &#8220;Events from $($log.Logname) event log&#8221;<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; Get-WinEvent -ea 0 -filterHashTable @{<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; LogName = $log.Logname;<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; StartTime = $bootTime;<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; EndTime = $bootTime.AddMinutes(5)}<\/p>\n<p style=\"padding-left: 30px\">&nbsp; }&nbsp;<\/p>\n<h2>Tracking the changes<\/h2>\n<p>So how did the changes do? Well, the original script took an average of 595 seconds to complete&mdash;that is nearly 10 minutes. The revised script took an average of 10 seconds to run!<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7573.hsg-7-15-13-01.png\"><img decoding=\"async\" title=\"Image of command output\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7573.hsg-7-15-13-01.png\" alt=\"Image of command output\" \/><\/a><\/p>\n<p>And it did not take all that long to make the change. In fact, it took me less than three minutes to change it. The cool part is that the change took less than half the time it took for the script to run. Bottom line, do not be afraid of <strong>FilterHashTable<\/strong>. Use it all the time. Filter to the left of the pipeline, not to the right of the pipeline.<\/p>\n<p>AB, that is all there is to using the <strong>FilterHashTable<\/strong> parameter to improve the performance of a Windows PowerShell event script. Join me tomorrow when I will talk about other cool Windows PowerShell 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><strong>Ed Wilson, Microsoft Scripting Guy<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, talks about using a filter hash table with Windows PowerShell to speed up boot trace parsing. &nbsp;Hey, Scripting Guy! I don&rsquo;t get it. You wrote a script yesterday, and said that the performance was bad. You suggested that you could improve the performance, but then you did not do [&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,60,3,4,45],"class_list":["post-3234","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-event-logs","tag-logs-and-monitoring","tag-performance","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, talks about using a filter hash table with Windows PowerShell to speed up boot trace parsing. &nbsp;Hey, Scripting Guy! I don&rsquo;t get it. You wrote a script yesterday, and said that the performance was bad. You suggested that you could improve the performance, but then you did not do [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/3234","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=3234"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/3234\/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=3234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=3234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=3234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}