Search code examples
sqlvb.netwmi

Use Environment.Tickcount to determine how long a computer has been on


I have been working a on a project in which i need a rough idea of how long a computer has been on.

To this end i have this code.

TimeSpan.FromMilliseconds(Environment.TickCount).ToString("dd:hh:mm:ss:ff") Can someone verify this is good?

What datatype is needed in sql for the above format? Thanks


Solution

  • a rough idea of how long a computer has been on:

    Windows reports that value various ways: as GetTickCount64 from kernel32, it is a PerformanceCounter and it is in WMI. It only reports system up time since the last reboot. If the last reboot was a week ago, it may only report 5 days if a net of 2 days was spent sleeping, so it is approximate.

    This makes sense since the system cannot be said to be "up" when sleeping/hibernating/stand by. TaskManager Performance tab:

    enter image description here

    Friend Shared Function GetWMIItem(wmiclass As String, qItem As String) As String
        Dim retVal As String = ""
        Dim query = String.Format("SELECT {0} FROM {1}", qItem, wmiclass)
    
        Using searcher As New ManagementObjectSearcher(query)
            For Each item As ManagementObject In searcher.Get
    
                Dim p = item.Properties(qItem)
                If (p IsNot Nothing) AndAlso (p.Value IsNot Nothing) Then
                    retVal = p.Value.ToString
                    ' should be nothing else
                    Exit For
                End If
    
            Next
        End Using
        Return retVal
    End Function
    

    To use it:

    Dim uptime = WMI.GetWMIItem("Win32_PerfFormattedData_PerfOS_System",
                   "SystemUpTime")
    Dim tsUp = TimeSpan.FromSeconds(Convert.ToInt32(uptime))
    

    The return is seconds, not milliseconds. If you need the last boot time:

    Dim lastBootStrVal = WMI.GetWMIItem("Win32_OperatingSystem", "LastBootUpTime")
    

    To read it, there is a special converter since it is in a special format:

    dtLastBoot = Management.ManagementDateTimeConverter.ToDateTime(LastBootTimeString)
    

    There is less code using PerformanceCounter (see link in the comment), but it is just as slow:

    Using uptime As New PerformanceCounter("System", "System Up Time")
        ' need to call NextValue once before using a PerformanceCounter
        uptime.NextValue
        ts = TimeSpan.FromSeconds(Convert.ToDouble(uptime.NextValue))
    End Using
    

    Otherwise they are all the same, GetTickCount64() offers better resolution, but it is still approximate depending on the amount of time sleeping.