How to query a machine’s up time using PowerShell

Sometimes we are wondering how long has a machine been up, or when was the last time a machine rebooted, but we can’t log in to find out because a user is currently logged on, and let’s say this user is an executive, and well… we don’t ever want to have to disturb this kind of users. Should you find yourself in this predicament, you can follow the below instructions to get this information in no time. and without the user ever noticing you were poking around his/her computer.

Using WMI, we can query the Win32_OperatingSystem class to get the “LastBootUpTime” property information. We simply need to run the following query:

 

Get-WmiObject Win32_OperatingSystem | Select CSname, LastBootUpTime

CSname                                                                    LastBootUpTime

——                                                                            ————–

MyPCName                                                              20160722100616.499782-240

 

The problem with the above query is that the time is displayed in timestamp format, so we need to convert this to DateTime doing the following:

 

Get-WmiObject Win32_OperatingSystem | Select @{L=’ComputerName’;E={$_.CSName}}, @{L=’LastBootUpTime’;E={$_.converttodatetime($_.LastBootUpTime)}}

ComputerName                                                       LastBootUpTime

————                                                                    ————–

MyPCName                                                                7/22/2016 10:06:16 AM

 

For those who are not familiar with the expression modifiers used above, the Select-Object cmdlet allows you to create custom labels and “customize” the output of another cmdlet. You can also add information that does not necessarily comes from the piped cmdlet (Get-WMIObject in this case). @{L=”<LabelName>” declares the label name as a Note Property type, ;E={<Expression>”}} opens a ScriptBlock where you can put one or more cmdlets (or a whole script if you want/need to) to get the exact value you want/need.

 

In this case, we just needed to convert the value from a timestamp format to DateTime format, but we could also have subtracted the LastBootUpTime from the Current Date to get UpTime instead. This is tricky though, when you convert the TimeStamp into DateTime, and then subtract it from the current date, you are left with a TimeSpan object. You will have to use the New-TimeSpan cmdlet (For PowerShell v3 and up), or the [TimeSpan] regular expression and then manipulate its output using yet another expression modifier. With the “little” piece of code, you can get a nice user-friendly uptime information:

 

@{L=’UpTime’;E={(New-timespan -end (Get-date) -start ([DateTime]$_.ConvertToDateTime($_.LastBootUpTime)) | Select @{l=’D’;e={“Days: $($_.Days) Hours:$($_.Hours) Minutes:$($_.Minutes)”}}).d}}

**Yes, this is only to get the user-friendly uptime, it makes you believe it’s easier to just calculate in your head the uptime using LastBootUpTime, but once the code is there, there is no more manual calculations required J**

 

The final command and output would display as follows:

Get-WmiObject Win32_OperatingSystem | Select @{L=’ComputerName’;E={$_.CSName}}, @{L=’UpTime’;E={(New-timespan -end (Get-date) -start ([DateTime]$_.ConvertToDateTime($_.LastBootUpTime)) | Select @{l=’D’;e={“Days: $($_.Days) Hours: $($_.Hours) Minutes: $($_.Minutes)”}}).d}}

 

ComputerName                                                       UpTime

————                                                                    ——

MyPCName                                                                Days: 3 Hours: 5 Minutes: 37

 

Now that we got all this, we need to make it into Function for repetitive and easy use. The final final code would look like this:

Function Get-UpTime {

Param (

[Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$true)]

[ValidateNotNull()]

[Alias(“CN”)]

$ComputerName)

Process{

ForEach ($Computer in $ComputerName) {

IF (Test-Connection -ComputerName $Computer -Count 1 -Quiet -ErrorAction SilentlyContinue){

Get-WmiObject -ComputerName $Computer -class Win32_OperatingSystem | Select @{L=’ComputerName’;E={$_.CSName}}, @{L=’UpTime’;E={([TimeSpan]”$((Get-date) – ([DateTime]$_.ConvertToDateTime($_.LastBootUpTime)))” | Select @{l=’D’;e={“Days: $($_.Days) Hours: $($_.Hours) Minutes: $($_.Minutes)”}}).d}}

}

Else {Write-Warning “$($Computer) was offline at the time of script execution”}

}

}

}

Get-UpTime

 

With this function, you can determine the UpTime of individual machines, or pipe a bulk of machines to the function, as follows:

Get-Content “C:\PCList” | Get-uptime

OR

Get-ADComputer -filter {Name -like “PCName*”} | Select -ExpandProperty Name | Get-uptime

 

ComputerName                                                          UpTime

————                                                                     ——

PCName-02                                                                Days: 0 Hours: 0 Minutes: 20

PCName-03                                                                Days: 3 Hours: 16 Minutes: 37

 

Just make sure that the piped cmdlet has a property ComputerName, or that you select the property like in the second example (Using ExpandProperty), or that there is no property name at all (like in the text file).

 

Hope you find this useful. Miguel out!