{"id":615,"date":"2025-11-28T13:46:22","date_gmt":"2025-11-28T13:46:22","guid":{"rendered":"https:\/\/eventlogxp.com\/blog\/?p=615"},"modified":"2025-11-28T13:46:22","modified_gmt":"2025-11-28T13:46:22","slug":"improving-event-log-filtering-in-powershell","status":"publish","type":"post","link":"https:\/\/eventlogxp.com\/blog\/improving-event-log-filtering-in-powershell\/","title":{"rendered":"Improving Event Log Filtering in PowerShell"},"content":{"rendered":"<p>Recently, one of our customers asked us to help port their PowerShell script to our script engine (built on FastScript\/Pascal Script). While helping them, we paid close attention to how they filtered events in PowerShell\u2014and noticed a common performance pitfall.<\/p>\n<p>Their original script filtered the System log by event type using a pipeline:<\/p>\n<pre>$elSysErr = Get-EventLog -LogName System | Where-Object EntryType -Eq 'Error'<\/pre>\n<p>Although the PowerShell pipeline is a powerful feature, using it here is unnecessary and inefficient. This command first loads <em>all<\/em> events from the System log into memory and only then filters them by type. A more efficient approach is to filter during retrieval:<\/p>\n<pre>$elSysErr = Get-EventLog -LogName System -EntryType 'Error'<\/pre>\n<p>This runs faster\u2014but there\u2019s a bigger issue.<br \/>\nYou <strong>shouldn\u2019t use Get-EventLog at all<\/strong>:<\/p>\n<ol>\n<li>Its filtering parameters are limited (no reliable way to filter by Event ID).<\/li>\n<li>It works only with classic\/legacy logs.<\/li>\n<li>It relies on deprecated Windows APIs.<\/li>\n<\/ol>\n<p>Microsoft now recommends using <strong>Get-WinEvent<\/strong>, which is documented here:<br \/>\n<a href=\"https:\/\/learn.microsoft.com\/en-us\/powershell\/module\/microsoft.powershell.diagnostics\/get-winevent\" target=\"_blank\" rel=\"noopener\">https:\/\/learn.microsoft.com\/en-us\/powershell\/module\/microsoft.powershell.diagnostics\/get-winevent<\/a><\/p>\n<h2>Rewriting the Command with Get-WinEvent<\/h2>\n<p>At first glance, you might simply replace Get-EventLog with Get-WinEvent:<\/p>\n<pre>$elSysErr = Get-WinEvent System | Where-Object LevelDisplayName -eq 'Error'<\/pre>\n<p>Or slightly better:<\/p>\n<pre>$elSysErr = Get-WinEvent System | Where-Object Level -eq 2<\/pre>\n<p>But this still requires reading the entire log first\u2014so you gain no performance benefits.<\/p>\n<p>The real power of Get-WinEvent is that it allows event filtering <em>before<\/em> reading the log. You can filter in two ways:<\/p>\n<ul>\n<li>Using a <strong>hashtable<\/strong><\/li>\n<li>Using an <strong>XML (XPath) query<\/strong><\/li>\n<\/ul>\n<p><strong>Using a Hashtable (the simplest approach)<\/strong><\/p>\n<pre>$elSysErr = Get-WinEvent -FilterHashTable @{LogName='System'; Level=2}<\/pre>\n<p><strong>Using an XPath query<\/strong><\/p>\n<pre>$elSysErr = Get-WinEvent -LogName 'System' -FilterXPath '*[System[(Level=2)]]'<\/pre>\n<h2>Performance Comparison<\/h2>\n<p>I ran all variations against my local System log (\u224850,000 events), using Measure-Command.<\/p>\n<p><strong>Pipeline filtering (Get-EventLog + Where-Object)<\/strong><\/p>\n<pre>Measure-Command { Get-EventLog -LogName System | Where-Object EntryType -Eq 'Error' }<\/pre>\n<p><a href=\"http:\/\/eventlogxp.com\/blog\/wp-content\/uploads\/2025\/11\/Get-EventLog1.png\" data-rel=\"lightbox-gallery-PllaJJmn\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" class=\"alignnone size-full wp-image-619\" src=\"http:\/\/eventlogxp.com\/blog\/wp-content\/uploads\/2025\/11\/Get-EventLog1.png\" alt=\"\" width=\"624\" height=\"158\" srcset=\"https:\/\/eventlogxp.com\/blog\/wp-content\/uploads\/2025\/11\/Get-EventLog1.png 624w, https:\/\/eventlogxp.com\/blog\/wp-content\/uploads\/2025\/11\/Get-EventLog1-300x76.png 300w\" sizes=\"(max-width: 624px) 100vw, 624px\" \/><\/a><\/p>\n<p><strong>\u2248 8 seconds<\/strong><\/p>\n<p><strong>Filter parameter (Get-EventLog -EntryType)<\/strong><\/p>\n<pre>Measure-Command { Get-EventLog -LogName System -EntryType 'Error' }<\/pre>\n<p><strong>\u2248 6 seconds<\/strong> (about 25% faster)<\/p>\n<p><strong>Pipeline filtering with Get-WinEvent<\/strong><\/p>\n<pre>Measure-Command { Get-WinEvent System | Where-Object Level -eq 2 }<\/pre>\n<p><a href=\"http:\/\/eventlogxp.com\/blog\/wp-content\/uploads\/2025\/11\/Get-WinEvent1.png\" data-rel=\"lightbox-gallery-PllaJJmn\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" class=\"alignnone size-full wp-image-620\" src=\"http:\/\/eventlogxp.com\/blog\/wp-content\/uploads\/2025\/11\/Get-WinEvent1.png\" alt=\"\" width=\"624\" height=\"180\" srcset=\"https:\/\/eventlogxp.com\/blog\/wp-content\/uploads\/2025\/11\/Get-WinEvent1.png 624w, https:\/\/eventlogxp.com\/blog\/wp-content\/uploads\/2025\/11\/Get-WinEvent1-300x87.png 300w\" sizes=\"(max-width: 624px) 100vw, 624px\" \/><\/a><\/p>\n<p><strong>\u2248 13 seconds<\/strong> (even slower!)<\/p>\n<p><strong>FilterHashTable (the fastest)<\/strong><\/p>\n<pre>Measure-Command { Get-WinEvent -FilterHashTable @{LogName='System'; Level=2} }<\/pre>\n<p><strong>\u2248 566 ms<\/strong><\/p>\n<p><strong>XPath filter<\/strong><\/p>\n<pre>Measure-Command { Get-WinEvent -LogName 'System' -FilterXPath '*[System[(Level=2)]]' }<\/pre>\n<p><strong>\u2248 600 ms<\/strong><\/p>\n<h3><strong>Conclusion:<\/strong><\/h3>\n<p>For performance, always use Get-WinEvent with <strong>-FilterHashTable<\/strong>, <strong>-FilterXML<\/strong>, or <strong>-FilterXPath<\/strong>.<\/p>\n<h2>Handling the \u201cNo events found\u201d error<\/h2>\n<p>One important detail rarely mentioned in online resources:<br \/>\nIf no events match the filter, Get-WinEvent throws a non-terminating error.<\/p>\n<p>This is not a big issue in interactive sessions, but in scripts it produces noisy output. To avoid this, simply ignore the error:<\/p>\n<pre>$elSysErr = Get-WinEvent -FilterHashTable @{LogName='System'; Level=2} -ErrorAction SilentlyContinue\r\nif ($elSysErr -eq $null) {\r\n \u00a0\u00a0 Write-Output \"no events match this filter\"\r\n} else {\r\n  \u00a0 # work with the result set\r\n}<\/pre>\n<h2><strong>How This Looks in Event Log Explorer Script Engine<\/strong><\/h2>\n<p>Here\u2019s how we port the same query into our scripting engine:<\/p>\n<pre>theApp.OpenLogQuery('', 'System', '*[System[(Level = 2)]]', True);<\/pre>\n<p>To measure performance:<\/p>\n<pre>var\r\n  StartTime, FinishTime: DWORD;\r\nbegin\r\n  StartTime := GetTickCount();\r\n  theApp.OpenLogQuery('', 'System', '*[System[(Level = 2)]]', True);\r\n  FinishTime := GetTickCount();\r\n  DebugOut('Executed in ', FinishTime - StartTime, ' ms');\r\nend.<\/pre>\n<p><a href=\"http:\/\/eventlogxp.com\/blog\/wp-content\/uploads\/2025\/11\/ElexOpenLogQuery.png\" data-rel=\"lightbox-gallery-PllaJJmn\" data-rl_title=\"\" data-rl_caption=\"\" title=\"\"><img loading=\"lazy\" class=\"alignnone size-full wp-image-618\" src=\"http:\/\/eventlogxp.com\/blog\/wp-content\/uploads\/2025\/11\/ElexOpenLogQuery.png\" alt=\"\" width=\"624\" height=\"407\" srcset=\"https:\/\/eventlogxp.com\/blog\/wp-content\/uploads\/2025\/11\/ElexOpenLogQuery.png 624w, https:\/\/eventlogxp.com\/blog\/wp-content\/uploads\/2025\/11\/ElexOpenLogQuery-300x196.png 300w\" sizes=\"(max-width: 624px) 100vw, 624px\" \/><\/a><\/p>\n<p>Result: <strong>\u2248 609 ms<\/strong><br \/>\nNot bad\u2014especially considering it not only retrieves the events, but also displays them.<\/p>\n<h2>Closing Thoughts<\/h2>\n<p>That\u2019s all for now. As the developers of <strong>Event Log Explorer<\/strong>, we strongly recommend using our software for tasks involving event log analysis. However, we fully recognize that PowerShell offers an exceptionally powerful scripting environment for managing Windows systems. When you choose to work with PowerShell, it\u2019s important to do so efficiently\u2014and using the right event filtering techniques can dramatically improve performance.<\/p>\n<a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-facebook nolightbox\" data-provider=\"facebook\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Facebook\" href=\"https:\/\/www.facebook.com\/sharer.php?u=https%3A%2F%2Feventlogxp.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F615&#038;t=Improving%20Event%20Log%20Filtering%20in%20PowerShell&#038;s=100&#038;p&#091;url&#093;=https%3A%2F%2Feventlogxp.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F615&#038;p&#091;images&#093;&#091;0&#093;=https%3A%2F%2Feventlogxp.com%2Fblog%2Fwp-content%2Fuploads%2F2025%2F11%2FEventLogFilterInPowerShell.jpg&#038;p&#091;title&#093;=Improving%20Event%20Log%20Filtering%20in%20PowerShell\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img alt=\"Facebook\" title=\"Share on Facebook\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none\" src=\"https:\/\/eventlogxp.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/facebook.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-twitter nolightbox\" data-provider=\"twitter\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Twitter\" href=\"https:\/\/twitter.com\/intent\/tweet?url=https%3A%2F%2Feventlogxp.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F615&#038;text=Check%20this%20Event%20Log%20Explorer%20blog%20post\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img alt=\"twitter\" title=\"Share on Twitter\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none\" src=\"https:\/\/eventlogxp.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/twitter.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-reddit nolightbox\" data-provider=\"reddit\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Reddit\" href=\"https:\/\/www.reddit.com\/submit?url=https%3A%2F%2Feventlogxp.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F615&#038;title=Improving%20Event%20Log%20Filtering%20in%20PowerShell\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img alt=\"reddit\" title=\"Share on Reddit\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none\" src=\"https:\/\/eventlogxp.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/reddit.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-pinterest nolightbox\" data-provider=\"pinterest\" target=\"_blank\" rel=\"nofollow\" title=\"Pin it with Pinterest\" href=\"https:\/\/pinterest.com\/pin\/create\/button\/?url=https%3A%2F%2Feventlogxp.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F615&#038;media=https%3A%2F%2Feventlogxp.com%2Fblog%2Fwp-content%2Fuploads%2F2025%2F11%2FEventLogFilterInPowerShell.jpg&#038;description=Improving%20Event%20Log%20Filtering%20in%20PowerShell\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img alt=\"pinterest\" title=\"Pin it with Pinterest\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none\" src=\"https:\/\/eventlogxp.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/pinterest.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-linkedin nolightbox\" data-provider=\"linkedin\" target=\"_blank\" rel=\"nofollow\" title=\"Share on Linkedin\" href=\"https:\/\/www.linkedin.com\/shareArticle?mini=true&#038;url=https%3A%2F%2Feventlogxp.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F615&#038;title=Improving%20Event%20Log%20Filtering%20in%20PowerShell\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px;margin-right:5px\"><img alt=\"linkedin\" title=\"Share on Linkedin\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none\" src=\"https:\/\/eventlogxp.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/linkedin.png\" \/><\/a><a class=\"synved-social-button synved-social-button-share synved-social-size-24 synved-social-resolution-single synved-social-provider-mail nolightbox\" data-provider=\"mail\" rel=\"nofollow\" title=\"Share by email\" href=\"mailto:?subject=Improving%20Event%20Log%20Filtering%20in%20PowerShell&#038;body=Check%20this%20Event%20Log%20Explorer%20blog%20post:%20https%3A%2F%2Feventlogxp.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F615\" style=\"font-size: 0px;width:24px;height:24px;margin:0;margin-bottom:5px\"><img alt=\"mail\" title=\"Share by email\" class=\"synved-share-image synved-social-image synved-social-image-share\" width=\"24\" height=\"24\" style=\"display: inline;width:24px;height:24px;margin: 0;padding: 0;border: none\" src=\"https:\/\/eventlogxp.com\/blog\/wp-content\/plugins\/social-media-feather\/synved-social\/image\/social\/regular\/48x48\/mail.png\" \/><\/a>","protected":false},"excerpt":{"rendered":"<p>Windows PowerShell provides several methods to filter event logs. In this article, we compare their performance to find the fastest. We also compared PowerShell log filtering with our Event Log Explorer scripting. <\/p>\n","protected":false},"author":2,"featured_media":623,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[83],"tags":[34,84,55,35],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/eventlogxp.com\/blog\/wp-json\/wp\/v2\/posts\/615"}],"collection":[{"href":"https:\/\/eventlogxp.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/eventlogxp.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/eventlogxp.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/eventlogxp.com\/blog\/wp-json\/wp\/v2\/comments?post=615"}],"version-history":[{"count":4,"href":"https:\/\/eventlogxp.com\/blog\/wp-json\/wp\/v2\/posts\/615\/revisions"}],"predecessor-version":[{"id":622,"href":"https:\/\/eventlogxp.com\/blog\/wp-json\/wp\/v2\/posts\/615\/revisions\/622"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/eventlogxp.com\/blog\/wp-json\/wp\/v2\/media\/623"}],"wp:attachment":[{"href":"https:\/\/eventlogxp.com\/blog\/wp-json\/wp\/v2\/media?parent=615"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/eventlogxp.com\/blog\/wp-json\/wp\/v2\/categories?post=615"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/eventlogxp.com\/blog\/wp-json\/wp\/v2\/tags?post=615"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}