Weekend Scripter: Use PowerShell to Get Boot-Up Trace Events

Weekend Scripter: Use PowerShell to Get Boot-Up Trace Events

  • Comments 2
  • Likes

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to get boot-up trace events.

Microsoft Scripting Guy, Ed Wilson, is here. This morning I am sipping the last of my English Breakfast tea with a little lemon grass and a crushed cinnamon stick. Not sure how I ran out of English Breakfast tea, but I did. Oh well. I still have Darjeeling tea—I just normally do not drink it first thing in the morning. I guess it is time to place an order to my favorite tea broker.

Anyway…

Anyone who knows anything about Windows knows that the three traditional event logs (System, Application, and Security) are not the be-all and end-all of logging and event gathering. For over six years, we have also had Event Tracing for Windows (ETW). Luckily, Windows PowerShell 2.0 introduced the Get-WinEvent cmdlet, which permits access to these trace logs.

Note  If you actually have a boot performance issue, you may want to read Jeff Stokes' blog post How to collect a good boot trace on Windows 7.

Picking up boot up trace events

One thing to keep in mind, is that some of the trace event logs require Admin rights. Windows PowerShell does not bypass security, rather it honors it. Therefore, if I need to access trace logs that require Admin rights, the easiest way to do this is to launch Windows PowerShell with Admin rights. If I do not, I see errors, such as these:

Image of error messages

I right-click the Windows PowerShell ISE icon, and select Run as administrator:

Image of menu

Now that I have the Windows PowerShell ISE running with Admin rights, it is time to write the script.

I first obtain the boot-up time. This code is shown here:

$bootTime = (Get-CimInstance win32_Operatingsystem).lastbootuptime

"Boot time is $($bootTime)"

Now I use the Get-WinEvent cmdlet to obtain a list of all of the event trace logs. I then use the Foreach command to walk through the collection as shown here:

Foreach($log in Get-WinEvent -ListLog *)

In my script block, I first display the name of each log:

"Events from $($log.Logname) event log"

Now I use the Get-WinEvent cmdlet to get all the log entries. I use the –ea 0 parameter because an error arises if the event log does not have entries. The command is shown here:

Get-WinEvent -LogName $log.Logname -ea 0 

In the following script, I pipe the entries to a Where-Object command and filter out five minutes after boot time:

where {$_.timecreated -gt $bootTime -and $_.timecreated -lt $bootTime.AddMinutes(5)}

Here is the completed script:

$bootTime = (Get-CimInstance win32_Operatingsystem).lastbootuptime

"Boot time is $($bootTime)"

Foreach($log in Get-WinEvent -ListLog *)

 {

  "Events from $($log.Logname) event log"

  Get-WinEvent -LogName $log.Logname -ea 0 |

  where {$_.timecreated -gt $bootTime -and $_.timecreated -lt $bootTime.AddMinutes(5)}

  }

The script is a bit slow in running, and I could certainly improve the efficiency by moving the time filter to the left of the pipeline (inside the Get-WinEvent cmdlet). As it is written, it gets every entry from every log, and then it filters it. This is inefficient. What keeps it from being a real performance dog is the pipeline.

If this was a script that I wanted to run more than once, I would most certainly “fix” it and improve the performance. But for a quick script that took less than five minutes to write, it is fine. The results from running the script are shown here:

Image of command output

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
  • @Ed

    You do not need this line:  "Events from $($log.Logname) event log"

    The type formatter will output that as needed and it will not be incorporated into the results.

    Try:

    $events=Foreach($log in Get-WinEvent -ListLog *){

        Get-WinEvent -LogName $log.Logname -ea 0 |

             where {$_.timecreated -gt $bootTime -and $_.timecreated -lt $bootTime.AddMinutes(5)}

    }

    $events

    See - it is still formatted to output the logname first.

  • @Ed - I should have noted that the output is the provider name which is loosely affiliated with the log for the newer Windows log files..

    This shows the affiliation:

    $events | SELECT Containerlog, ProvidernAME