1

It seems like in powershell,

echo ASDF | Select-String ASDF

outputs the obvious string, ASDF.

However, if i attempt to look at WinEvents, and look for an output, i.e.

Get-WinEvent -ListLog * | Select-String antrea

It seems as if the raw text is not scanned.

Whats the right way to use Select-STring as if it were a standard unix Grep ?

enter image description here

jayunit100
  • 17,388
  • 22
  • 92
  • 167
  • 2
    Get-WinEvent returns objects with properties, not strings. You'll want to use Where-Object to filter the output - `Get-WinEvent -ListLog * -ErrorAction SilentlyContinue | Where-Object logname -match 'ssh'` – Daniel Apr 28 '21 at 20:30
  • This is because `Get-WinEvent` returns an `object` not a `string` / `string[]`. To get all the `LogNames` related to `SSH` you can do `Get-WinEvent -Listlog *ssh*` – Santiago Squarzon Apr 28 '21 at 20:32
  • 2
    In short: Unfortunately, [`Select-String`](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/select-string) uses simple `.ToString()` stringification on its input objects rather than using the rich for-display representation produced by PowerShell's output-formatting system that you see when printing to the console. The workaround is to pipe to `Out-String -Stream` first; see [the answer](https://stackoverflow.com/a/58732143/45375) to the linked duplicate for details. – mklement0 Apr 28 '21 at 20:33
  • 1
    Or you can force the output to string using Out-String `(Get-WinEvent -ListLog * -ErrorAction SilentlyContinue | Out-String) -split "`r?`n" | Select-String ssh` – Daniel Apr 28 '21 at 20:33
  • 2
    Good point, @Daniel, though using `Out-String -Stream` is simpler. – mklement0 Apr 28 '21 at 20:35
  • 2
    Since `Get-WinEvent` outputs `System.Diagnostics.Eventing.Reader.EventLogRecord` objects and those objects don't have a `ToString()` override, you do not get the expected results. The object's wrapper provides its own `ToString()` method which simply outputs the object type when executed. You are effectively performing a string search against the string `System.Diagnostics.Eventing.Reader.EventLogRecord`. – AdminOfThings Apr 28 '21 at 20:43

1 Answers1

2

Pipelines in PowerShell are slightly different from UNIX style shells - instead of passing string output from one command to the next, PowerShell passes raw .NET object references.

So you'll want to inspect the properties of the objects returned by Get-WinEvent - here using the Where-Object cmdlet:

Get-WinEvent -ListLog * |Where-Object LogName -Match SSH

If you want to inspect which properties are available on a specific object, use the Get-Member cmdlet:

PS ~> Get-WinEvent -ListLog * |Get-Member -MemberType Property

   TypeName: System.Diagnostics.Eventing.Reader.EventLogConfiguration

Name                           MemberType Definition
----                           ---------- ----------
IsClassicLog                   Property   bool IsClassicLog {get;}
IsEnabled                      Property   bool IsEnabled {get;set;}
LogFilePath                    Property   string LogFilePath {get;set;}
LogIsolation                   Property   System.Diagnostics.Eventing.Reader.EventLogIsolation LogIsolation {get;}
LogMode                        Property   System.Diagnostics.Eventing.Reader.EventLogMode LogMode {get;set;}
LogName                        Property   string LogName {get;}
LogType                        Property   System.Diagnostics.Eventing.Reader.EventLogType LogType {get;}
MaximumSizeInBytes             Property   long MaximumSizeInBytes {get;set;}
OwningProviderName             Property   string OwningProviderName {get;}
ProviderBufferSize             Property   System.Nullable[int] ProviderBufferSize {get;}
ProviderControlGuid            Property   System.Nullable[guid] ProviderControlGuid {get;}
ProviderKeywords               Property   System.Nullable[long] ProviderKeywords {get;set;}
ProviderLatency                Property   System.Nullable[int] ProviderLatency {get;}
ProviderLevel                  Property   System.Nullable[int] ProviderLevel {get;set;}
ProviderMaximumNumberOfBuffers Property   System.Nullable[int] ProviderMaximumNumberOfBuffers {get;}
ProviderMinimumNumberOfBuffers Property   System.Nullable[int] ProviderMinimumNumberOfBuffers {get;}
ProviderNames                  Property   System.Collections.Generic.IEnumerable[string] ProviderNames {get;}
SecurityDescriptor             Property   string SecurityDescriptor {get;set;}
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • 1
    Hadn't noticed that you had already posted an answer when I closed this as a duplicate. My assumption was that the OP was looking for a quick-and-dirty search through the for-display output you get in the console, without having to specify or worry about specific property names. – mklement0 Apr 28 '21 at 20:39
  • 1
    Undoubtedly, querying properties is ultimately the best solution, but I've come to appreciate the quick-and-dirty approach in interactive use. https://github.com/PowerShell/PowerShell/issues/10726#issuecomment-567628146 advocates for making `Select-String` default to using the formatting system's string representations (implied `Out-String -Stream`). In the meantime, I've rolled my own wrapper function with this functionality, available from [this Gist](https://gist.github.com/mklement0/46fea9e6e5ef1a3ceaf681c976cb68e3). It has become an indispensable tool for me. – mklement0 Apr 28 '21 at 20:42