Invoke Get-WinEvent without parameters

You may be used to invoke cmdlets without parameters and get a nice default end-user experience. However, you may be surprised by the default behavior of the Get-WinEvent cmdlet. In a Windows PowerShell 5.1 console, you may encounter the following error:

Get-WinEvent : The data is invalid
At line:1 char:1
+ Get-WinEvent
+ ~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-WinEvent], EventLogInvalidDataException
+ FullyQualifiedErrorId : The data is invalid,Microsoft.PowerShell.Commands.GetWinEventCommand

This issue has already been reported a long time ago on uservoice.

Let’s try to find out what happens behind the scene, when you invoke the Get-WinEvent cmdlet without parameters.

The default parameter set is named GetLogSet and has the following parameters:

# Get the name of the default parameter set
Get-Command Get-WinEvent | Select DefaultParameterSet

# What are its parameters
(Get-Command Get-WinEvent).ParameterSets | 
Where isDefault | 
Select -ExpandProperty Parameters | Out-GridView

Notice that none of them is mandatory.

What kind of error is this?

$Error[0] | Select -Property *

We actually get an error that has the following fully qualified name System.Diagnostics.Eventing.Reader.EventLogInvalidDataException

If you invoke the Get-WinEvent cmdlet with one of the common parameters, the Debug switch, you get the following:

Get-WinEvent -Debug

An xml query is created with 434 log names (the index starts at 0).

Let’s extract this xml query.
If you remember my post about how to Make Get-WinEvent cmdlet perform quicker, you know that the XML query also appears in the Verbose stream.
By merging the output and verbose stream and removing the ending dot and the first line, I can capture the xml query in a variable named q.

# oneliner
$q = ((( $(try {Get-WinEvent -Verbose -ErrorAction Stop 4>&1} catch {}).Message) -split "`n")[1]) -replace '\.',''

# same oneliner split on multiple lines for a better readability
$q = (
   try {
    Get-WinEvent -Verbose -ErrorAction Stop 4>&1
   } catch {}
  ) -split "`n"
) -replace '\.',''


The captured xml query is valid because casting it to the XML type alias or accelerator (for [System.Xml.XmlDocument]) doesn’t throw an error.

By using a dichotomic approach, it’s possible to find out when the error occurs.

# There are 434 Query nodes in this XML query
([xml]$q).QueryList.Query | Measure
# A query with 257 Paths fails
Get-WinEvent -FilterXml (
'<QueryList><Query>{0}</Query></QueryList>' -f "$(
Select-Xml -Xml ([xml]$q) -XPath '//Query' |
Select -First 257
# A query with 256 Paths succeeds
Get-WinEvent -FilterXml ([xml]('<QueryList><Query>{0}</Query></QueryList>'-f "$((Select-Xml -Xml ([xml]$q) -XPath '//Query' | Select -First 256).Node.InnerXML)"))

It appears that the number of Paths is the culprit. You can have a single Query node with a huge number of Paths or a huge number of Query nodes with a Path, it doesn’t make a difference. In both cases having more than 256 Paths will produce this undesirable behavior.

You get actually the same error if you do the following

Get-WinEvent -LogName *
# Use the Debug switch to uncover the XML query:
Get-WinEvent -LogName * -Debug

The LogName is the non-mandatory parameter that belongs to the default parameter set named GetLogSet. It has the same behavior as invoking the Get-WinEvent cmdlet without parameters.

I haven’t seen many blog posts about this error and the following shed some lights on the 256 Paths limit:
Nice work Craig 🙂

Quick post: Review Windows Defender notifications

My son has dowloaded some zip files to be used when he plays Minecraft. The Windows Defender real-time scan blocked and quarantined these files. I had a notification the next time I logged on the computer.
I dismissed too quickly the notification and wanted to get more info about what happened.
I went in the Windows Security dashboard but I couldn’t find any info in the History 😦

After some Google-fu, I found the following page on about Review event logs and error codes to troubleshoot issues with Windows Defender Antivirus.

It appears that you can either use PowerShell to retrieve these events from the log 😀

Get-WinEvent -FilterHashtable @{
 ProviderName = 'Microsoft-Windows-Windows Defender'; 
} | 
Select -Last 2 -ExpandProperty Message

or a filter in the event viewer.