;; 
;;=====================================================================================----- 
;; 
;;FUNCTION       WMIUptime() 
;; 
;;ACTION         Calculates the length of time the system has been up. 
;; 
;;AUTHOR         Glenn Barnas 
;; 
;;VERSION        1.1  - 2007/04/05 
;; 
;;HISTORY        1.0  - 2003/05/11 - Initial Release 
;;               1.1  - 2007/04/05 
;;                Authentication, rename to WMIUptime 
;;		  Adjustment for uptime across timezone changes 
;; 
;;SYNTAX         WMIUptime([Target] [,AuthPtr]) 
;; 
;;PARAMETERS     Target - OPTIONAL - String 
;;               - The name of system to query 
;; 
;;               AuthPtr - OPTIONAL - Object 
;;               - The pre-authenticated WMI object pointer. 
;;                 Use WMIAuthenticate() udf to create the AuthPtr value. 
;;                 AuthPtr is not needed if user has admin rights. 
;;; 
;;REMARKS        Gets both the boot and local time from the remote system,  
;;               eliminating issues with timezone differences between target 
;;               and client.  
;; 
;;RETURNS        Array containing Days, Hours, Minutes, and Seconds of uptime. 
;;               Also returns the cTime value in element 4 
;; 
;;DEPENDENCIES   WMI support 
;; 
;;TESTED WITH    W2K, WXP, W2K3 
;; 
;;EXAMPLES       $Host = '' 
;;               $Up   = WMIUptime($Host) 
;;               $Host has been up for ' $Up[0] ' days!' 
;; 
;;               $Host = 'server' 
;;               $objWMI = WMIAuthenticate('computer', 'userid', 'User-P@ss!') 
;;               $Up = WMIUptime($Host, $objWMI) 
;;               'Secure host ' $Host ' has been up for ' $Up[0] ' days!' 
; 
Function WMIUpTime(OPTIONAL $_Computer, OPTIONAL $_pAuth)
 
  Dim $_Bt[3], $_Ct[3], $_U[4]			; time arrays for boot, current, and uptime 
  Dim $_, $_O					; Index var, Offset flag 
  Dim $_B, $_C					; boot and current time strings 
  Dim $_Bo, $_Co				; boot and current time offsets 
  Dim $_objWMIService, $_colItems, $_objItem	; WMI object vars 
 
  $WMIUptime = -1				; default to invalid value 
 
  ; insure a properly formatted computer name, default to local computer is not specified 
  $_Computer = IIf(Not $_Computer, '.', Join(Split($_Computer,'\'),''))
 
  ; If a pre-authenticated WMI object pointer was provided, use it, otherwise create a new object pointer 
  If $_pAuth
    $_objWMIService = $_pAuth
  Else
    $_objWMIService = GetObject('winmgmts:{impersonationLevel=impersonate}!\\' + $_Computer + '\root\cimv2')
    If @ERROR Exit Val('&' + Right(DecToHex(@ERROR), 4)) EndIf
  EndIf
 
  $_colItems = $_objWMIService.ExecQuery("Select * from Win32_OperatingSystem",,48)
  For each $_objItem in $_colItems
 
    $_B = $_objItem.LastBootUpTime	; host-local boot time 
    $_C = $_objItem.LocalDateTime	; host-local current time 
 
    ; format is YYYYMMDDhhmmss.ssssss+ooo (or -ooo) 
    ; Get the timezone offset. The offset will not play into the calculation unless 
    ; the timezone switched between reboots, such as going from Standard to DaylightSavings 
    If InStr($_B, '-') Or InStr($_B, '+')
      $_Bo = Val(SubStr($_B, 23))	; boot timezone offset 
      $_Co = Val(SubStr($_C, 23))	; current timezone offset 
      $_O = ($_Co - $_Bo) * 60		; find the difference, usually will be zero 
    EndIf
 
    ; strip off the fractional seconds and time zone offset value 
    $_B = Split($_B, '.')[0]
    $_C = Split($_C, '.')[0]
 
    ; format is now YYYYMMDDhhmmss - put into array 
    $_Bt[0] = Val(SubStr($_B, 1, 4)) - 2000
    $_Bt[1] = Val(SubStr($_B, 5, 2))
    $_Bt[2] = Val(SubStr($_B, 7, 2))
    $_Bt[3] = 1.0 * SubStr($_B,13) + 60.0 * SubStr($_B,11,2) + 3600.0 * SubStr($_B,9,2)
    $_Ct[0] = Val(SubStr($_C, 1, 4)) - 2000
    $_Ct[1] = Val(SubStr($_C, 5, 2))
    $_Ct[2] = Val(SubStr($_C, 7, 2))
    $_Ct[3] = 1.0 * SubStr($_C,13) + 60.0 * SubStr($_C,11,2) + 3600.0 * SubStr($_C,9,2)
 
 
    ; Convert dates to Days, then convert to seconds and add the time value 
    If $_Bt[1] < 3
      $_Bt[1] = $_Bt[1] + 12
      $_Bt[0] = $_Bt[0] - 1
    EndIf
    $_B = $_Bt[2] + ( 153 * $_Bt[1] - 457 ) / 5 + 365 * $_Bt[0] + $_Bt[0] / 4 - $_Bt[0] / 100 + $_Bt[0] / 400 - 306
    $_B = CDbl($_B) * 86400.0
    $_B = $_B + $_Bt[3]
    If $_Ct[1] < 3
      $_Ct[1] = $_Ct[1] + 12
      $_Ct[0] = $_Ct[0] - 1
    EndIf
    $_C = $_Ct[2] + ( 153 * $_Ct[1] - 457 ) / 5 + 365 * $_Ct[0] + $_Ct[0] / 4 - $_Ct[0] / 100 + $_Ct[0] / 400 - 306
    $_C = CDbl($_C) * 86400.0
    $_C = $_C + $_Ct[3]
 
    ; Calculate uptime as cTime, then convert to days / hours / minutes / seconds 
    $_ = $_C - $_B + $_O
    $_U[4] = $_			; return the cTime value 
    $_U[0] = Int($_ / 86400)
    $_ = $_ Mod 86400
    $_U[1] = $_ / 3600
    $_ = $_ Mod 3600
    $_U[2] = $_ / 60
    $_U[3] = $_ Mod 60
 
 Next
 
  $WMIUptime = $_U
 
EndFunction