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].Exception.GetType().Fullname $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 {} ).Message ) -split "`n" )[1] ) -replace '\.','' [xml]$q
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 ( | |
[xml]( | |
'<QueryList><Query>{0}</Query></QueryList>' -f "$( | |
( | |
Select-Xml -Xml ([xml]$q) -XPath '//Query' | | |
Select -First 257 | |
).Node.InnerXML | |
)" | |
) | |
) | |
# 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:
http://www.powershellish.com/blog/2015-01-19-get-winevent-max-logs
Nice work Craig 🙂
I confess I didn’t go into depth but do I get it right that if one would limit the parameters to be returned to the ones of interest this would reduce/eliminate the given error?
The problem is not the parameters, it’s the 256 Paths limit.
If they set the limit to 4096, we would not get this error.
If they cannot raise the limit, they should limit the Paths to the 256 limit or throw a more specific error saying that this limit has been reached.
Doh 🙂
So in other words enabling the GPO “Local Computer Policy > Computer Configuration > Administrative Templates > System > Filesystem > Enable Win32 long paths” should do the trick then?
Would be at least a way for bigger environments.
It’s not a NTFS filesystem limit. Here it’s about the number of eventlog names. The XML query built references these with a Path property.
Pingback: Dew Drop – December 30, 2019 (#3101) | Morning Dew