12

I need to develop a program in C# find out when was Windows started or shutdown.

Is there a log file that I can read to know Windows start and shutdown times? Or do you have any ideas how to do so?

EDIT :

With the help of Mr. Reed Copsey, the best answer is found under this question.

2
  • In Windows >= 8 with Fast Boot / Startup enabled all the solutions provided here so far are "wrong", because shutdown = "close all programs, log out the user and hibernate". Environment.TickCount might work, but sometimes it yields negative numbers. Commented Oct 6, 2016 at 7:17

9 Answers 9

15

According to this article you can use WMI to get the last boot date/time.

// define a select query
SelectQuery query =
    new SelectQuery(@"SELECT LastBootUpTime FROM Win32_OperatingSystem
       WHERE Primary='true'");

// create a new management object searcher and pass it
// the select query
ManagementObjectSearcher searcher =
    new ManagementObjectSearcher(query);

// get the datetime value and set the local boot
// time variable to contain that value
foreach(ManagementObject mo in searcher.Get())
{
    dtBootTime =
        ManagementDateTimeConverter.ToDateTime(
            mo.Properties["LastBootUpTime"].Value.ToString());

    // display the start time and date
    txtDate.Text = dtBootTime.ToLongDateString();
    txtTime.Text = dtBootTime.ToLongTimeString();
}
2
  • 1
    Thanks, but I need to get a log of more than just last time.
    – YAM
    Commented Sep 13, 2011 at 19:35
  • 1
    LastBootUpTime give you Date and time the operating system was last restarted. Commented Feb 14, 2022 at 4:49
6

System.Environment.TickCount has a 24.8 days limitation.
This is because TickCount is a millisecond value contained in a signed 32 bits value.

Windows API exposes these two functions:
GetTickCount - returns a 32 bits value - available from Windows 2000
GetTickCount64 - returns a 64 bits value - available from Vista/Windows Server 2008

You can use GetTickCount64 this way:

using System.Runtime.InteropServices;  

[DllImport("Kernel32.dll")]  
static extern long GetTickCount64();  

DateTime osStartTime = DateTime.Now - new TimeSpan(10000 * GetTickCount64());
1
  • Or without the knowledge that one ms is 10000 ticks: DateTime bootDateTime = DateTime.Now.AddMilliseconds(-(double)Win32.GetTickCount64()); Commented Jan 31, 2023 at 11:40
5

As Reed pointed out you could access the Event Logs and see when they were created. AFAIK there are no specific event entries for system startup/shutdown, but you could look for services that are usually started/stopped with Windows. Though using this approach means it won't be 100% accurate, say if it crashes or it's manually started/stopped/restarted. One event I consider is the most accurate is EventLog service start/stop event.

if (EventLog.Exists("System"))
{
    var log = new EventLog("System", Environment.MachineName, "EventLog");

    var entries = new EventLogEntry[log.Entries.Count];
    log.Entries.CopyTo(entries, 0);

    var startupTimes = entries.Where(x => x.InstanceId == 2147489653).Select(x => x.TimeGenerated);
    var shutdownTimes = entries.Where(x => x.InstanceId == 2147489654).Select(x => x.TimeGenerated);
}

Edit

Turns out there was a shutdown event. You can replace the Linq to get it:

var shutdownEvents = entries.Where(x => x.InstanceId == 2147484722);
0
4

You can use the classes in System.Diagnostics.Eventing.Reader to access the system Event Logs.

6
  • 2
    Would you please give me more details of how to read desired data then? Thanks
    – YAM
    Commented Sep 13, 2011 at 19:37
  • @Yas_EG: It's a bit too long for a simple query here - but there are good samples on MSDN showing how to read and query data using these classes. See: msdn.microsoft.com/en-us/library/bb671200(v=VS.90).aspx and msdn.microsoft.com/en-us/library/bb671197(v=VS.90).aspx Commented Sep 13, 2011 at 19:46
  • 1
    I'm curious why the downvotes - This is the only working solution that lets you get historical startup/shutdown times that's been listed thus far.... Commented Sep 13, 2011 at 19:47
  • @Yas_EG: Here's a simpler example:stackoverflow.com/questions/6185608/… It shows a console app that will read shutdown events... Commented Sep 13, 2011 at 19:57
  • 1
    @Yag_EG: If you look for Event ID 6005, you'll see when the Event Logging Service starts. This happens immediately on boot... Commented Sep 13, 2011 at 20:49
4

You could use the "System Up Time" performance counter to get the start time of the system:

 PerformanceCounter systemUpTime = new PerformanceCounter("System", "System Up Time");

 systemUpTime.NextValue();
 TimeSpan upTimeSpan = TimeSpan.FromSeconds(systemUpTime.NextValue());
 Console.Out.WriteLine(DateTime.Now.Subtract(upTimeSpan).ToShortTimeString());

Hope, this helps.

1
  • 2
    This one takes current datetime and substracts the period of time windows has been runing. If you are "hibernateing" your machine, result won't be valid. Commented Sep 26, 2013 at 9:28
3

Last Restart time can be found using this piece of code

static void Main(string[] args)
    {          
        TimeSpan t = TimeSpan.FromMilliseconds(System.Environment.TickCount);
        Console.WriteLine( DateTime.Now.Subtract(t));          
    }
1
  • 2
    System.Environment.TickCount has a 24.8 days limitation.
    – Kiquenet
    Commented Apr 5, 2019 at 6:37
1

Some more options:

1
  • Thanks, but I need to get a log of more than just last time
    – YAM
    Commented Sep 13, 2011 at 19:37
1

In .NET 5 and .NET Core 3, you can use the Environment.TickCount64 property.

var t = TimeSpan.FromMilliseconds(Environment.TickCount64);
var lastBootTime = DateTime.UtcNow.Subtract(t);
Console.WriteLine(lastBootTime);
1

Here is a collected code that can be executed, including the code above.

This was written in .NET 4.6.1, which is usually executed.

You can choose any method :

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

namespace ConsoleEventLogSample1
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args is null) throw new ArgumentNullException(nameof(args));


            // EventLog
            Console.WriteLine($"EventLog = Last shutdown time : " +
                $"{GetSystemLastTimeByEventLog(false):yyyy-MM-dd HH:MM:ss}, " +
                $"Last startup time : {GetSystemLastTimeByEventLog(true):yyyy-MM-dd HH:MM:ss}"); // ms(fff) is not displayed

            // Registry
            Console.WriteLine($"Registry = Last shutdown time : " +
                $"{GetSystemLastShutdownTimeByRegistry():yyyy-MM-dd HH:MM:ss.fff}");

            // WMI
            Console.WriteLine($"WMI = Last startup time : " +
                $"{GetSystemLastStartupTimeByWMI():yyyy-MM-dd HH:MM:ss.fff}");

            Console.ReadLine();
        }

        static DateTime GetSystemLastTimeByEventLog(bool direction)
        {
            // Do not check for presence or not : Items that must exist
            var log = new EventLog("System", Environment.MachineName, "EventLog");

            var entries = new EventLogEntry[log.Entries.Count];
            log.Entries.CopyTo(entries, 0);

            if (direction)
            {
                return entries.Where(x => x.InstanceId == 2147489653).Select(x => x.TimeGenerated).Last();
            }
            else
            {
                return entries.Where(x => x.InstanceId == 2147489654 || x.InstanceId == 2147489656).Select(x => x.TimeGenerated).Last();
            }
        }

        static DateTime GetSystemLastShutdownTimeByRegistry()
        {
            // Do not check for presence or not : Items that must exist
            string sKey = @"System\CurrentControlSet\Control\Windows";
            using (Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(sKey))
            {
                string sValueName = "ShutdownTime";
                byte[] val = (byte[])key.GetValue(sValueName);
                long valueAsLong = BitConverter.ToInt64(val, 0);
                return DateTime.FromFileTime(valueAsLong);
            }
        }

        static DateTime GetSystemLastStartupTimeByWMI()
        {
            // Do not check for presence or not : Items that must exist
            SelectQuery query = new SelectQuery(@"select LastBootUpTime from Win32_OperatingSystem where Primary='true'");

            ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
            DateTime lastdt = new DateTime();

            foreach (ManagementObject mo in searcher.Get())
            {
                lastdt = ManagementDateTimeConverter.ToDateTime(mo.Properties["LastBootUpTime"].Value.ToString());
                break;
            }

            return lastdt;
        }

    }
}

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