7

Is there a way to find out when the system was last shutdown?

I know there's a way to find out last boot up time using the LastBootUpTime property in Win32_OperatingSystem namespace using WMI.

Is there anything similar to find out last shutdown time?

Thanks.

Sameet
  • 2,191
  • 7
  • 28
  • 55
  • 3
    You'll also need to consider whether you care when a machine has its power pulled - you're not going to get an event for that. – serialhobbyist Oct 27 '09 at 16:16

3 Answers3

8

Assuming Windows is shutdown smoothly. It stores it in the registry:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Windows\ShutdownTime

It is stored as an array of bytes but is a FILETIME.

While there may be a better way, I have used this before and think it works:

    public static DateTime GetLastSystemShutdown()
    {
        string sKey = @"System\CurrentControlSet\Control\Windows";
        Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(sKey);

        string sValueName = "ShutdownTime";
        object val = key.GetValue(sValueName);

        DateTime output = DateTime.MinValue;
        if (val is byte[] && ((byte[])val).Length == 8)
        {
            byte[] bytes = (byte[])val;

            System.Runtime.InteropServices.ComTypes.FILETIME ft = new System.Runtime.InteropServices.ComTypes.FILETIME();
            int valLow = bytes[0] + 256 * (bytes[1] + 256 * (bytes[2] + 256 * bytes[3]));
            int valTwo = bytes[4] + 256 * (bytes[5] + 256 * (bytes[6] + 256 * bytes[7]));
            ft.dwLowDateTime = valLow;
            ft.dwHighDateTime = valTwo;

            DateTime UTC = DateTime.FromFileTimeUtc((((long) ft.dwHighDateTime) << 32) + ft.dwLowDateTime);
            TimeZoneInfo lcl = TimeZoneInfo.Local;
            TimeZoneInfo utc = TimeZoneInfo.Utc;
            output = TimeZoneInfo.ConvertTime(UTC, utc, lcl);
        }
        return output;
    }
JDunkerley
  • 12,355
  • 5
  • 41
  • 45
  • +1 fine approach, I deleted my post, as this is far more accurate it seems – Abel Oct 27 '09 at 16:49
  • sorry, I couldn't resist, there seems to be slightly easier way to convert a byte array to a `DateTime`, hope you don't mind, but I couldn't have done it without your answer :) – Abel Oct 27 '09 at 17:01
8

(everything here is 100% courtesy of JDunkerley's earlier answer)

The solution is above, but the approach of going from a byte array to DateTime can be achieved with fewer statements using the BitConverter.The following six lines of code do the same and give the correct DateTime from the registry:

public static DateTime GetLastSystemShutdown()
{
    string sKey = @"System\CurrentControlSet\Control\Windows";
    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);
}
Community
  • 1
  • 1
Abel
  • 56,041
  • 24
  • 146
  • 247
  • Hmm, thanks for accepting, but the solution provided here is totally based on JDunkerley's answer, he should receive all credit, basically ;-) – Abel Nov 09 '09 at 19:22
  • It seems like this value isn't updated when the computer crashes :( – Pavenhimself Sep 10 '14 at 09:13
  • 1
    @Pavenhimself: if the computer crashes, an event in the eventlog is created _after_ the next boot (the BSOD itself obviously prevents the actual Shutdowntime to be written to the registry, or anything else for that matter, the only thing the system does on BSOD is to create a dump file). You can check for EventID 6008, source EventLog. To find the actual time, check the timestamp on the BSOD dump file. – Abel Sep 10 '14 at 17:16
  • Thank you Abel, found it in Log = "System" and Source = "EventLog" and then filtered the EventLogEntry for EventID == 6008 :) Works like a charm – Pavenhimself Sep 12 '14 at 08:08
  • In windows 10 "ShutdownTime" is not working properly – MCv Mar 10 '17 at 07:58
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));          
    }
Sravan
  • 596
  • 1
  • 9
  • 19