3

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?

7
  • You could store a timestamp in the registry when your program runs. If the timestamp is present, indicating your program has been run before, you could get the system uptime and see if your timestamp is before or after it. stackoverflow.com/questions/972105/… Commented Dec 17, 2020 at 13:28
  • You could add a scheduleded task which is triggered on startup to write to a file. Then empty that file when the hardware settings have been sent. Commented Dec 17, 2020 at 13:29
  • I think there should be a system call that tells you this
    – 66Gramms
    Commented Dec 17, 2020 at 13:29
  • Is there any volatile setting on the PCIe board which you could use to remember that its settings have been set? Commented Dec 17, 2020 at 13:37
  • 1
    Powering up is always recorded in the Event log. You don't need to write anything to the registry or use any scheduled tasks that may actually fail themselves Commented Dec 17, 2020 at 14:18

4 Answers 4

2

See How to know when was Windows started or shutdown on how to get the last boot time.

You can write the boot time to a file. When you start your program you can check if the saved value match the current value or not, and update the file with the new value if needed.

See also Getting last reboot time

1
  • 1
    Those methods don't, in general, work with Windows 10 due to a shutdown not resetting the timer. A reboot does, a shutdown does not. Commented Dec 17, 2020 at 13:35
1

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.

0

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!

0

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.

Not the answer you're looking for? Browse other questions tagged or ask your own question.