How to determine if the PC has been rebooted since my program's last run?

Viewed 560

The title says it all.

What is the best way to determine if the PC has been rebooted since my program's last run?

Context: C# - Win XP and on

A piece of hardware (PCIe board) that I'm configuring requires the settings to only be sent once per power cycle but users may close and open the program multiple times before power cycling the PC.

I'm thinking I need some sort of a global reference that my program starts/sets while starting then it can check if said global reference is running/true at each start up and act accordingly.

Ideas? Suggestions?

4 Answers

As user Panagiotis Kanavos commented, an event log entry is written when Windows boots.

If you have a look in Event Viewer in the System log, you will find those entries have Event ID == 12, which is accessed in code by using the InstanceId property of an EventLogEntry (the EventID property is deprecated).

So you can get all those log entries, sort them, and get the latest one, like this:

using System;
using System.Diagnostics;
using System.Linq;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            EventLog systemLog = new EventLog("System");
            var bootEntry = systemLog?.Entries.Cast<EventLogEntry>().
                Where(x => x.InstanceId == 12).
                OrderByDescending(x => x.TimeGenerated).
                FirstOrDefault();

            if (bootEntry != null)
            {
                Console.WriteLine("Last boot: " + bootEntry.TimeGenerated.ToString("yyyy-MM-dd HH:mm:ss"));
            }
            else
            {
                Console.WriteLine("Could not open System log or no boot event found.");
            }

            Console.ReadLine();
        }
    }
}

(Tested as working on Windows 10 20H2.)

Now, my computer has a fast SSD, and my experience of reading the event logs from an HDD is that that can be sloooooow, so you might want to get the entry in some background task.

It looks possible to look up the boot time in the Windows Event Log. I haven't verified this, but maybe this can work for you.

Manually, you can use the Event Viewer to find the PC's boot time. This will get you the information you need to make the programmatics call to get the relevant data. You'd do something like this (not a complete solution):

var logs = EventLog.GetEventLogs();
// not sure about this; you may need to change the search below...
var log = logs.Single(l => l.LogDisplayName == "Application and Services Log");
// search entries
var bootEntries = log.Entries.Where(x => ...);
...

This uses these APIs

So, it looks like it's possible to drill down to the entry you need, grab out the timestamp and do your various checks. Good luck!

Save the last boot time (e.g. in user.config) and then compare it with the current value. Environment.TickCount64 keeps track of the time since the system started.

var storedLastBootTime = LoadBootTimeFromSettings();

var currentTime = DateTime.UtcNow.Ticks / TimeSpan.TicksPerMillisecond;
var lastBootTime = currentTime - Environment.TickCount64;

if (lastBootTime > storedLastBootTime)
{
    // A system reboot must have taken place!
}

SaveBootTimeToSettings(lastBootTime);

If the saved value is greater, a restart must have taken place. To handle that you need to save the current time too.

Related