Expert Commentary: 2012 Scripting Games Beginner Event 7

Expert Commentary: 2012 Scripting Games Beginner Event 7

  • Comments 2
  • Likes

Summary: Microsoft PFE, Michael Frommhold, provides expert commentary for 2012 Scripting Games Beginner Event 7.

Microsoft Scripting Guy, Ed Wilson, is here. Michael Frommhold is the expert commentator for Beginner Event 7.

Photo of Michael Frommhold

Michael is a senior premier field engineer for Microsoft Germany. His technology foci are Active Directory, development (.NET, PoSh, VBS) and platforms. Apart from supporting customer Active Directory infrastructures, he provides workshops and customized knowledge transfers to teach customers how to implement coding and scripting against Active Directory and platform technologies.

In beginner event 7, you are required to display a list of all enabled logs on the computer that contain at least one entry.

Solution

If we open the Event Viewer management console, we see some event logs in the root of the Windows Logs folder and a huge number nested underneath in Applications and Services Logs.

All the event logs that are visible in these folders can be collected through the WMI class Win32_NTEventlogFile or the Windows PowerShell cmdlet Get-EventLog (because Get-EventLog is a wrapper around Win32_NTEventlogFile). The reason that you cannot see all the event logs underneath Microsoft, for example, is that Win32_NTEventlogFile is only enumerating in the root of %SystemRoot%\System32\Winevt\Logs folder for event logs as shown here:

If you call the following command from Windows PowerShell, you will get the same list of event logs as shown in the previous image.

Get-EventLog -list | Format-Table Log

Here is the list that is generated:

Log                                                                                                                                                                         

---                                                                                                                                                                          

ActivIdentity                                                                                                                                                                

Application                                                                                                                                                                 

HardwareEvents                                                                                                                                                               

HP Connection Manager                                                                                                                                                        

Internet Explorer                                                                                                                                                           

Key Management Service                                                                                                                                                       

Media Center                                                                                                                                                                 

OAlerts                                                                                                                                                                     

ODiag                                                                                                                                                                        

Operations Manager                                                                                                                                                           

OSession                                                                                                                                                                    

Security                                                                                                                                                                     

System                                                                                                                                                                       

Windows PowerShell

Unfortunately this list contains only a partial result of the information that we are looking for. Because we know that we can get the list of all present event logs through the command-line utility, wevtutil.exe, by calling:

wevtutil el

Plus, we know we can collect the information about the enabled state of an event log by calling:

wevtutil gl <logname>

Plus, how many entries are in the event log by calling:

wevtutil gli <logname>

To script the concatenation of these three calls would definitely not meet the Scripting Games quality standard, so hopefully there's something we can call from Windows PowerShell directly.

And lucky us—there is another cmdlet that will do the trick:

Get-WinEvent -ListLog *

If we do not call the Windows PowerShell cmdlet from an elevated prompt, we will get some errors (like when retrieving information about the Security event log). To avoid the error messages and to collect design points, we use the ability to set common parameters. In particular we set:

-ErrorAction 'SilentlyContinue'

…which results in…

Get-WinEvent -ListLog * -ErrorAction 'SilentlyContinue'

The next design point to meet is to display only enabled event logs with at least one entry in the log.

To find out what properties we can use, let's inspect the type of objects that are returned by the Get-WinEvent call:

Get-WinEvent -ListLog * -ErrorAction 'SilentlyContinue'  | Get-Member

And the properties are:

Name

----

RecordCount

IsEnabled

Cool. There are the two properties that expose the information we are looking for, so let's pipe this into a Where-Object cmdlet:

Get-WinEvent -ListLog * -ErrorAction 'SilentlyContinue'  |

Where-Object{$_.IsEnabled -and $_.RecordCount -gt 0}

What should come next? The sorting—to give us the event log with highest number of entries in the first row. That's easy. We just pipe the result of the Where-Object cmdlet into a Sort-Object cmdlet and sort it by RecordCount in a descending order:

Get-WinEvent -ListLog * -ErrorAction 'SilentlyContinue'  |
Where-Object{$_.IsEnabled -and $_.RecordCount -gt 0} |
Sort-Object -Property RecordCount -Descending

We are nearly finished with our one-liner. The last thing to do is select the properties that we want to show as output (LogName and RecordCount). So we have to pipe the result from the Sort-Object cmdlet to the Format-Table cmdlet:

Get-WinEvent -ListLog * -ErrorAction 'SilentlyContinue'  |
Where-Object{$_.IsEnabled -and $_.RecordCount -gt 0} |
Sort-Object -Property RecordCount -Descending |
Format-Table Logname, RecordCount

And here you go…here is what we see in the output window:

Image of command output

Have fun with testing!

~Michael
   PFE | Have keyboard. Will travel.

2012 Scripting Games Guest Commentator Week Part 2 will continue tomorrow when we will present the scenario for Event 8.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi Michael, it doesn't show the log (Microsoft-Windows-WMI-Activity/Trace) even if it has a record and is enabled.

    Thanks for your help

    http://scottalvarino.com

  • Hi Scott,

    you are absolutely right and I'm so sorry not seeing that (none of them was enabled on my machine...).

    Get-Winevent will not show you the Debug or Analytic logs if you do not use the switch -Force (and you are not running elevated). But even when using the -Force switch -> unfortunately the object in the collection will hav $null as value for RecordCount - unless we connect the eventlog file directly via

     $collection = Get-WinEvent -path PathToEvLogFile -Oldest

    -> the .Count property of the returned Eventlogentrycollection will give us then the record count.

    Another wee problem is that we get the PathToEvLogFile as for ex. %SystemRoot%\System32\Winevt\Logs\Microsoft-Windows-WMI-Activity%4Trace.etl -> the environment variable has to be expanded. This means we lost the possibility to write this as a oneliner.

    Functional code (quick'n'dirty):

    function ExpandEnvironmentStringInPath([string] $Logpath)

    {

    $bmatch = $Logpath -match "^%\w+%\\"

    $var = $Matches[0] -replace "\\", ""

    $var = $var -replace "%", ""

    $var = [Environment]::GetEnvironmentVariable($var) + "\"

    $Logpath -replace "^%\w+%\\", $var

    }

    function GetRecordCountFromLogFile([string] $Logpath)

    {

    $colev = Get-WinEvent -Path $Logpath -Oldest -ErrorAction 'SilentlyContinue'

    if ($colev.Count -eq $null)

    {

    0

    }

    else

    {

    $colev.Count

    }

    }

    $caller = New-Object Security.Principal.WindowsPrincipal( [Security.Principal.WindowsIdentity]::GetCurrent( ) )

    if ( -not ($caller.IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator ) ) )

    {

       Write-Error "To collect info about all event log files this script must be started elevated!" -ErrorAction Stop

    }

    $collog = Get-WinEvent -ListLog * -Force -ErrorAction 'SilentlyContinue' | Where-Object{($_.IsEnabled -and $_.RecordCount -gt 0) -or ($_.IsEnabled -and $_.RecordCount -eq $null)}

    ForEach ($log in $collog)

    {

    if ($log.RecordCount -eq $null)

    {

    $log.RecordCount = GetRecordCountFromLogFile(ExpandEnvironmentVariableInPath($log.LogFilePath))

    }

    }

    $collog | Where-Object{$_.RecordCount -gt 0} | Sort-Object -Property RecordCount -Descending | Format-Table Logname, RecordCount

    Best regards / Viele Grüße

    Michael

    PFE | Have keyboard. Will travel.