Find last boot up time of remote Windows computers using WMI

From Svendsen Tech Powershell Wiki

Jump to: navigation, search

I added the obvious, basic examples below, and even an example function, for those with simpler needs.

What this article is mostly about: For some reason you find yourself wanting to know when a range of servers or workstations were last booted. Here you will find a way of doing it both simply and more advanced against a range of target computers.

I researched the topic a little before writing this article, and I saw various more or less sane ways of determining the last boot-up time, but what I'll be demonstrating here is with WMI from PowerShell, which I think should be a sane approach in most scenarios.

The last time I needed this was when we were deploying some software via a GPO startup script and wanted to see which computers were supposed to have run the script. I already knew about the LastBootUpTime property in the Win32_OperatingSystem class, and considered rolling some one-liners, but realized the very WMI wrapper I had already written would be ideal for taking care of most of the dirty work - and to produce an XML report of the collected data. Later this XML report is turned into CSV and finally we get a readable report.

See this article for how to get computer names from an OU in AD - or the entire AD.

Contents






A Simple Example Against A Single Target Host

Here's a simple example against the remote host "winxpssd":

PS C:\> $LastBootUpTime = Get-WmiObject Win32_OperatingSystem -Comp winxpssd | Select -Exp LastBootUpTime
PS C:\> [System.Management.ManagementDateTimeConverter]::ToDateTime($LastBootUpTime)

Wednesday, June 13, 2012 3:10:45 AM

And we see that the XP workstation was last booted on Wednesday, June 13th.

Should you prefer an unreadable one-liner - behold:

PS C:\> [System.Management.ManagementDateTimeConverter]::ToDateTime( (gwmi Win32_OperatingSystem -Comp winxpssd).LastBootUpTime )

Wednesday, June 13, 2012 3:10:45 AM


A Simple PowerShell Function For Checking Last Boot Up Time Using WMI

The -ComputerName parameter for Get-WmiObject accepts an array of strings, but if one of them has a terminating error, all the other data is lost. Considering this, a very basic, generic function for this that you could put in your profile, or dot-source when needed, might look something like this:

<#
.SYNOPSIS
Get the last boot up time of a remote Windows computer via WMI.

.PARAMETER ComputerName
Target host or hosts to retrieve the last boot up time for.
#>

function Get-LastBootUpTime {
    
    param([Parameter(Mandatory=$true)][string[]] $ComputerName)
    
    foreach ($Computer in $ComputerName) {
        
        [Management.ManagementDateTimeConverter]::ToDateTime( (Get-WmiObject -Class Win32_OperatingSystem -Computer $Computer | Select -Exp LastBootUpTime) )
        
    }
    
}

To use it, you'd do something like this, where you first dot-source the script to get the function in the current scope, and then use the function:

PS C:\> . C:\prog\PowerShell\Get-LastBootUpTime.ps1
PS C:\> Get-LastBootUpTime winxpssd,2008r2esxi,win2k

Wednesday, June 13, 2012 3:10:45 AM
Wednesday, June 13, 2012 3:08:50 AM
Thursday, June 14, 2012 7:51:22 AM


PS C:\> Get-Help Get-LastBootUpTime -Detailed

Multiple Target Computers

NB! This example uses an older version of the Get-WmiObject-Wrapper script and is no longer entirely accurate.

Now to the slightly more interesting part where I demonstrate how to process a bunch of remote computers and create a simple report of when they were last booted. Shamelessly, I promote my own Get-WmiObject-Wrapper script. You can download it from that link. The documentation there is fairly extensive, but if you follow this guide you should be good to go without too much hassle.

  • Download both the files at the link above and put them in your working directory.
  • Retrieve target computer names from AD, if necessary, and put them in a text file or a variable holding an array of target computer names. If you have a text file of target computers, use the parameter "-ComputerName (gc .\hosts.txt)".
  • Retrieve the desired data using the WMI wrapper script against target hosts.


Get Data In XML Format

First I get all the computers in my little lab AD and then I collect data with the Get-WmiObject-Wrapper script.

PS C:\PowerShell> Import-Module ActiveDirectory

PS C:\PowerShell> $Computers = Get-ADComputer -filter '*' | Select -Exp Name
PS C:\PowerShell> $Computers.Count
15

PS C:\PowerShell> .\Get-WmiObject-Wrapper.ps1 -ComputerName $Computers -OutputFile BootTime.xml
-MultiClassProperty 'Win32_OperatingSystem:LastBootUpTime'

It looks like the output file was specified without a full path. I need a full path.
You provided: 'BootTime.xml'
Suggested path: 'C:\PowerShell\BootTime.xml'

Use the suggested path? (y/n) [yes]: y

Script start time: 06/14/2012 06:56:12
Processing SS-WIN7...
Creating XML...
Successfully saved 'C:\PowerShell\BootTime.xml'
Script start time: 06/14/2012 06:56:12
Script end time:   06/14/2012 06:56:34

PS C:\PowerShell> notepad .\BootTime.xml

Now we have BootTime.xml which contains the collected data, error messages and "no ping reply" messages.

Create A CSV Report Of Retrieved Boot Times

This creates a CSV report of the target computers from which we were successfully able to retrieve the last boot-up time. If you use the property "NoPing", you get computers that did not respond to ping - and if you use "Error", you get computers that had WMI errors.

PS C:\PowerShell> .\Gwmi-Wrapper-Report.ps1 -XmlFile .\BootTime.xml -Property LastBootUpTime
                   -Headers -CsvDelimiter ',' | Set-Content BootTimeCSV.csv

You can then process it with Import-Csv:

PS C:\PowerShell> Import-Csv .\BootTimeCSV.csv

Computer            Class                         Property                 Value
--------            -----                         --------                 -----
2008R2ESXI          Win32_OperatingSystem         LastBootUpTime           20120613030850.500000+120
2008R2ESXI2         Win32_OperatingSystem         LastBootUpTime           20120613024717.341720+120
SIEMENS             Win32_OperatingSystem         LastBootUpTime           20120613101758.500000+120
VISTA64ESXI         Win32_OperatingSystem         LastBootUpTime           20120614061652.593622+120
WIN2K               Win32_OperatingSystem         LastBootUpTime           20120614075122.000000+120
WIN7ESXI            Win32_OperatingSystem         LastBootUpTime           20120510081619.678297+120
WINXPSSD            Win32_OperatingSystem         LastBootUpTime           20120613031045.498972+120

Finally - The Human-readable Report

Now, those time stamps aren't too useful as they are, so we spaghetti a little one-liner to just spit out what we want to look at. First create a WMI object on which to call the ConvertToDateTime() method, and then use Foreach-Object to produce a human-readable report, sorted on date. Use "Sort -Descending 'Last Boot Up Time'" to reverse the sort order.

PS C:\PowerShell> $Wmi = Get-WmiObject Win32_OperatingSystem
PS C:\PowerShell> Import-Csv .\BootTimeCSV.csv | Select Computer,
@{n='Last Boot Up Time';e={$Wmi.ConvertToDateTime($_.Value)}} |
Sort 'Last Boot Up Time'

Computer                                                    Last Boot Up Time
--------                                                    -----------------
WIN7ESXI                                                    5/10/2012 8:16:19 AM
2008R2ESXI2                                                 6/13/2012 2:47:17 AM
2008R2ESXI                                                  6/13/2012 3:08:50 AM
WINXPSSD                                                    6/13/2012 3:10:45 AM
SIEMENS                                                     6/13/2012 10:17:58 AM
VISTA64ESXI                                                 6/14/2012 6:16:52 AM
WIN2K                                                       6/14/2012 7:51:22 AM

Personal tools