1

I would like to know how long the PC has been started. That's why I made the following routine:

Public Function LipPCIsOn() As String
  Dim iTempoPC As Integer
  Dim tTempoPC As TimeSpan
  Dim strTempoPC As String
  iTempoPC = System.Environment.TickCount
  tTempoPC = TimeSpan.FromMilliseconds(iTimePC)
  strTempoPC = tTempoPC.Duration.ToString("hh:mm:ss")
  Return strTempoPC
End Function

But I do not understand, the PC despite having been started by 3 minutes it tells me: 7:54:36 Where's the mistake? Thank you all

Antony
  • 83
  • 11
  • 2
    `having been started by 3 minutes` - started or waken up? – GSerg Feb 10 '20 at 14:14
  • Look at using the [Performance Counter](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.performancecounter?view=netframework-4.8) class, [here's](https://stackoverflow.com/a/972189/1797425) an answer using it for your exact need. – Trevor Feb 10 '20 at 15:22
  • 1
    It shows the time since the last full restart, not just shut down and start up, because Windows saves some state to disk to make the next start up faster. – Andrew Morton Feb 10 '20 at 15:29
  • Yep, there's something fishy in the conversion between TickCount and FromTicks. My pc has been on for 2h40' and returns around 340095703 ticks, which can't be immediately converted to 2h40' – Alessandro Mandelli Feb 10 '20 at 15:41
  • @AndrewMorton can you please substantiate where your information is taken from? Environment.TickCount Property from docs@ms literally says: "Gets the number of milliseconds elapsed since the system started." – Alessandro Mandelli Feb 10 '20 at 16:02
  • @AlessandroMandelli Are you using Windows 10? That is where the issue occurs. Do you happen to have fast startup disabled? That causes the power on timer to start from zero when Windows boots. – Andrew Morton Feb 10 '20 at 16:09
  • Yes, I have fast startup enabled and in fact in the Task manager, performance pane, it shows more than 3 days and 23 hours... despite having rebooted in the early afternoon. +1 for you. -1 for M$ – Alessandro Mandelli Feb 10 '20 at 16:43
  • I think the punctuation in your code is off? `-`, `:`, and `"` need repair – Matt Johnson-Pint Feb 18 '20 at 20:39
  • @Matt Yes in my code there are errors writing this the correct code: Public Function LipPCIsOn() As String Dim iTempoPC As Integer Dim tTempoPC As TimeSpan Dim strTempoPC As String iTempoPC = System.Environment.TickCount tTempoPC = TimeSpan.FromMilliseconds(iTimePC) strTempoPC = tTempoPC.Duration.ToString("hh:mm:ss") Return strTempoPC End Function – Antony Feb 19 '20 at 17:09
  • @Antony. Please [edit your original question](https://stackoverflow.com/posts/60152151/edit) instead of putting that in comments. Thanks. – Matt Johnson-Pint Feb 19 '20 at 17:28
  • @Matt I've already updated my original question.. Thank – Antony Mar 08 '20 at 14:30

2 Answers2

2

There may be some other source of the last power-on time, but you can use the Windows System Event Log to get the last event from Kernel-Boot:

Function GetLastPowerOn() As DateTime?
    Dim systemEventLog = New EventLog()
    systemEventLog.Log = "System"

    Dim lastPowerOn = systemEventLog.Entries.Cast(Of EventLogEntry).
        Where(Function(eu) eu.Source = "Microsoft-Windows-Kernel-Boot").
        OrderByDescending(Function(ev) ev.TimeGenerated).FirstOrDefault()

    Return lastPowerOn?.TimeGenerated

End Function

I do not know the behaviour for if there is no entry, so I assumed that a Nullable(Of DateTime) would do. If you want to clear your System event log, you could let us know what happens; I don't want to do that.

Unfortunately, it takes ages to return a value (e.g. about 7 seconds on this computer), so you might want to call it asynchronously. Here is an example which uses one button and two labels on a form:

Public Class Form1
    Dim tim As Timer

    Friend Async Function GetLastPowerOnAsync() As Task(Of DateTime?)
        Dim systemEventLog = New EventLog() With {.Log = "System"}
        Dim tsk = Await Task.Factory.StartNew(Function()
                                                  Return systemEventLog.Entries.Cast(Of EventLogEntry).
                                                  Where(Function(eu) eu.Source = "Microsoft-Windows-Kernel-Boot").
                                                  OrderByDescending(Function(ev) ev.TimeGenerated).
                                                  FirstOrDefault()
                                              End Function)

        Return tsk?.TimeGenerated

    End Function

    Sub timTick(sender As Object, e As EventArgs)
        Label1.Text = DateTime.Now.ToString("HH:mm:ss")
    End Sub

    Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim lpo = Await GetLastPowerOnAsync()
        If lpo.HasValue Then
            Label2.Text = lpo.Value.ToString("yyyy-MM-dd HH:mm:ss")
        Else
            Label2.Text = "No System event log entry with a source of Microsoft-Windows-Kernel-Boot entry found."
        End If

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        tim = New Timer() With {.Interval = 500}
        AddHandler tim.Tick, AddressOf timTick
        tim.Start()

    End Sub

    Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
        RemoveHandler tim.Tick, AddressOf timTick
        tim.Dispose()

    End Sub

End Class
Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
  • Thank you all. I just wanted to know if my routine was right or not. I wouldn't want to use too complex features. – Antony Feb 11 '20 at 12:25
  • @Antony If you want to know at what time Windows was started (and hence how long ago), then your method won't work properly with Windows 10 (not your fault). – Andrew Morton Feb 11 '20 at 12:35
  • @Antony All the code in my second part apart from `Function GetLastPowerOnAsync()` only serves the purpose of demonstrating a way to use that function. – Andrew Morton Feb 11 '20 at 12:37
-1

Thank you all. I just wanted to point out that: 1) my PC did not make a real shutdown but a suspension; 2) the correct code I rewrote is:

Public Function LipPCIsOnNew() As String
  Dim EventoLogApp As New System.Diagnostics.EventLog("System")
  Dim OraACCENSIONE As Date, stMachineName As String

  ' search from the end, to find the last boot faster
  For i = EventoLogApp.Entries.Count - 1 To 1 Step -1

     If EventoLogApp.Entries(i).InstanceId.ToString = 1 Then

        OraACCENSIONE = EventoLogApp.Entries(i).TimeGenerated

        stMachineName = EventoLogApp.Entries(i).MachineName.ToString

        Exit For
     End If
  Next

  Return OraACCENSIONE.ToString

End Function

Now everything is ok

Thank you all

Antony
  • 83
  • 11