Why metrics matter and how PowerShell can help

- select the contributor at the end of the page -

Ever hear the saying, If you can’t measure it, you can’t manage it? It’s one of my favorite quotes because it rings so true when dealing with IT infrastructure. The ability to build metrics around stats, like uptime, is a great way to see the level of quality you’re delivering to customers. Your servers probably don’t go down every day, so it’s possible that you don’t even realize they’re bombing every month or so. Downtime like this results in loss—it’s a major hindrance to business. It all boils down to this: Without metrics you have no way to improve. You have no number; no target goal. Thankfully, you can easily avoid this problem.

Building a useful script

One of the most common metrics we can get is general “uptime.” Uptime might mean different things to different people but, today, we’ll think of it as the time in which a Windows server has been booted up. Granted, it’s not the most sophisticated metric for uptime, but it gives you an idea of how often a server is rebooted, shutdown or lost power for whatever reason.

Whenever a Windows computer is booted up it will always register an event 6005 in the System event log; when shutdown, it will always register an event ID 6006 in the System event log. Using PowerShell and some simple date comparisons we can build a script that will show us when a computer was booted up, when it was shut down, when it came back up and when it got shut down again. We can see this information as far back as the event log goes. By then comparing the startup and shutdown dates we can build a helpful report of the times a server was down and for how long.

First, we’ll need to query the System event log. I like to use Get-WinEvent because it’s typically faster than using Get-EventLog. To only query the System event log and the 6005 ID to find all startup times, we’ll need to use the -FilterHashTable parameter.

  $ComputerName = ‘SOMEPC’
$filterHt = @{
'LogName' = 'System'
'ID' = 6005
$StartEvents = Get-WinEvent -ComputerName $ComputerName -
FilterHashtable $filterHt
$StartTimes = $StartEvents.TimeCreated

You can see that I’m querying the computer SOMEPC for all of the start events. Since we don’t need any of the other information in the event, we'll then create a $StartTimes variable that will contain only the dates in which the computer was booted up.

Next, we’ll do the same only for the 6006 event ID. But this time, in order to get the date comparisons working right, we’ll order the events by oldest first (by default, Get-WinEvent orders the events newest first).

  $filterHt.ID = 6006
$StopEvents = Get-WinEvent -ComputerName $ComputerName -
FilterHashtable $filterHt -Oldest
$StopTimes = $StopEvents.TimeCreated

We now have all start and stop events on the computer. This means it’s time to loop through all of the start times to see if we can find a corresponding stop time. We'll use a foreach loop here to iterate over each of the start times and will then check for the corresponding stop time by finding the closest stop time that’s greater than the start time.

If we can’t find a stop time, this is probably because the computer is still running. In that case, just use the current time as the stop time. This will get the most current uptime.

  foreach ($startTime in $StartTimes) {
$StopTime = $StopTimes | where { $_ -gt $StartTime } | select -
First 1
if (-not $StopTime)
$StopTime = Get-Date
$output = [ordered]@{
'Startup' = $StartTime
'Shutdown' = $StopTime
'Uptime (Days)' = [math]::Round((New-TimeSpan -Start
$StartTime -End $StopTime).TotalDays, 2)
'Uptime (Min)' = [math]::Round((New-TimeSpan -Start
$StartTime -End $StopTime).TotalMinutes,2)

Remember, we want to see the date and time the computer has stopped and started each time. We also want to see how long that was between those two times. To get this information in a nice format, we'll create a custom object (shown above). This custom object has properties of Startup, Shutdown, Uptime (Days) and Uptime (Min) which will be the difference of the two dates.

If all goes as planned you should get a nice output like this:


And it's as simple as that. I’ve put this script out on my Github repo if you’d like to download it and give it a shot!

Get our content first. In your inbox.


Adam Bertram

is an independent consultant, technical writer, trainer and presenter. Adam specializes in consulting and evangelizing all things IT automation mainly focused around Windows PowerShell. Adam is a Microsoft Windows PowerShell MVP, 2015 powershell.org PowerShell hero and has numerous Microsoft IT pro certifications. He is a writer, trainer and presenter and authors IT pro course content for Pluralsight. He is also a regular contributor to numerous print and online publications and presents at various user groups and conferences. You can find Adam at his site listed below or on Twitter at @adbertram.