Author Posts

August 23, 2016 at 2:39 pm

Hello!

I am using PS to write a .ps1 to use as a logon script. The script should get the value of system uptime, then perform some simple logic based on that value. I am coming up short (beginner) and could use some help. I think my script is falling down as I suspect my $uptime variable may be storing a function, but not the value of the completed function. I am still trying to assign the Value to the variable. Here is my attempt at scripting this:

function Get-SystemUptime {
    $operatingSystem = Get-WmiObject Win32_OperatingSystem
   "$((Get-Date) - ([Management.ManagementDateTimeConverter]::ToDateTime($operatingSystem.LastBootUpTime)))" 
}

$uptime = Get-SystemUptime

if (Get-SystemUptime -ge 14) {
   write-host "Reboot your computer"
   }

To me, this has created a function which does work and returns '1.00:43:03:4281895', for my particular system.

I then assigned it to $uptime variable.

I am then trying to use logic that IF the value of my function -ge 14.00, do this thing.

Right now the Get-SystemUptime function and $uptime variable return what I need, but I do not think my IF logic is getting the returned value.

I will add that the ultimate goal is to use this .ps1 as a logon script in our environment that will run once when a user logs in. If the computer has not been reboot in more than 14 days, I will need to call something else in the script to display an annoying message, prompting the user to reboot.

Any assistance is appreciated! Thank you!

  • This topic was modified 2 years, 1 month ago by  camelCreed.
  • This topic was modified 2 years, 1 month ago by  camelCreed.
  • This topic was modified 2 years, 1 month ago by  camelCreed.

August 23, 2016 at 2:56 pm

UPDATE:

I got this working, here:

function Get-SystemUptime {
    $operatingSystem = Get-WmiObject Win32_OperatingSystem
   "$((Get-Date) - ([Management.ManagementDateTimeConverter]::ToDateTime($operatingSystem.LastBootUpTime)))" 
}

$uptime = Get-SystemUptime

if ($uptime -ge "14.00:00:00:0000000") {
   write-host "Reboot your computer"
   }

August 23, 2016 at 3:05 pm

Your function is returning a string. If the string was the hours, it would work, but seeing if 14 is equal 1.00:43:03:4281895 to won't ever work because it's returning a timespan as a string.

PS C:\Users\Rob> $uptime.GetType()

IsPublic IsSerial Name                                     BaseType                                                                                                                                         
-------- -------- ----                                     --------                                                                                                                                         
True     True     String                                   System.Object                                                                                                                                    

So, if we modify you function to return a TimeSpan object, then we get properties such as days to perform a comparison against:

function Get-SystemUptime {
    $operatingSystem = Get-WmiObject Win32_OperatingSystem
    New-TimeSpan -Start ([Management.ManagementDateTimeConverter]::ToDateTime($operatingSystem.LastBootUpTime)) -End (Get-Date)
}

$uptime = Get-SystemUptime

if ($uptime.Days -ge 14) {
   write-host "Reboot your computer"
}

You'll note if you look at $uptime now, it has properties that can be used to do comparisions:

PS C:\Users\Rob> $uptime.GetType()

IsPublic IsSerial Name                                     BaseType                                                                                                                                         
-------- -------- ----                                     --------                                                                                                                                         
True     True     TimeSpan                                 System.ValueType                                                                                                                                 



PS C:\Users\Rob> $uptime


Days              : 6
Hours             : 19
Minutes           : 56
Seconds           : 46
Milliseconds      : 457
Ticks             : 5902064572319
TotalDays         : 6.83109325499884
TotalHours        : 163.946238119972
TotalMinutes      : 9836.77428719833
TotalSeconds      : 590206.4572319
TotalMilliseconds : 590206457.2319

August 23, 2016 at 3:09 pm

Hi Creed,

When comparing date/time in PowerShell, it is easiest to work with datetime objects.
However as you may have found out yourself, the LastBootUpTime property of the returned WMI object does not return a datetime object, but a string object.

Fortunately though the WMI object itself has the 'ConvertToDateTime' method, that can be used to convert the string to a proper datetime object.

Changing your 'Get-SystemUptime' function to this:

function Get-SystemUptime {
    $operatingSystem = Get-WmiObject Win32_OperatingSystem
    $operatingSystem.ConvertToDateTime($operatingSystem.LastBootUpTime)
}

Makes it return a proper datetime object, as can be seen here:

PS > Get-SystemUptime

22. august 2016 13:17:47



PS > (Get-SystemUptime).GetType()

IsPublic IsSerial Name                                     BaseType                                          
-------- -------- ----                                     --------                                          
True     True     DateTime                                 System.ValueType                                  



PS > 

Having changed your function you can compare the returned datetime object, to a datetime object where you subtract the desired number of days (14) as follows:

if ( (Get-SystemUptime) -lt (Get-Date).AddDays(-14) ) {
    write-host "Reboot your computer"
}

August 23, 2016 at 3:13 pm

Powershell lets you cheat because it's converting the string to a timespan automatically for -ge comparison logic to work. Powershell is an object oriented language, so you want to really try to leverage an object like the TimeSpan example because you aren't assuming that Powershell is going to perform the correct type conversion.

August 23, 2016 at 5:09 pm

This is excellent help. Thank you so much, Rob and Christian.

I went with Rob's suggestion as it gave the object properties to work with in a way that I understood.

Now when I query $uptime.Days, I return '1', which is very easy to make a comparison to.

Thank you!!

August 23, 2016 at 7:59 pm

bonus, if you use ciminstance it's already a datetime object.

(Get-CimInstance Win32_OperatingSystem).lastbootuptime.gettype()