使用.NET获取最后一次Windows关机事件的日期和时间

7
有没有办法找出系统上次关机的时间?
我知道可以使用WMI中Win32_OperatingSystem命名空间中的LastBootUpTime属性来查找最后一次启动时间。
有类似的方法来查找上次关机时间吗?
谢谢。

3
你还需要考虑一下,当机器断电时你是否关心 - 这种情况不会触发事件。 - serialhobbyist
3个回答

8
假设Windows已经平稳关机,它会将此信息存储在注册表中:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Windows\ShutdownTime

它以字节数组的形式存储,但是它是一个FILETIME。

虽然可能有更好的方法,但我之前使用过这种方法,并认为它有效:

    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;
    }

+1 很好的方法,我删除了我的帖子,因为这似乎更准确 - Abel
抱歉,我忍不住了,似乎有一种稍微更简单的方法将字节数组转换为“DateTime”,希望你不介意,但如果没有你的答案,我是做不到的 :) - Abel

8
(以下所有内容均由JDunkerley早期的回答提供)

解决方案已经给出,但是使用BitConverter可以用更少的语句将byte数组转换为DateTime。下面的六行代码实现相同的功能,并从注册表中给出正确的DateTime

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);
}

嗯,谢谢您接受了我的回复,但是这个解决方案完全基于JDunkerley的答案,他应该得到所有的功劳,基本上是;-) - Abel
当电脑崩溃时,似乎这个值没有被更新 :( - Pavenhimself
1
@Pavenhimself:如果计算机崩溃,那么在下一次启动后会创建一个事件日志中的事件(显然,BSOD本身会阻止实际的关机时间被写入注册表或任何其他内容,系统在BSOD上唯一做的事情就是创建转储文件)。您可以检查EventID 6008,源EventLog。要查找实际时间,请检查BSOD转储文件的时间戳。 - Abel
谢谢Abel,我在日志=“System”和源=“EventLog”中找到了它,然后过滤了EventID == 6008的EventLogEntry :) 完美运行。 - Pavenhimself
在Windows 10中,“ShutdownTime”无法正常工作。 - MCv

3

使用以下代码可以找到上次重启时间

static void Main(string[] args)
    {          
        TimeSpan t = TimeSpan.FromMilliseconds(System.Environment.TickCount);
        Console.WriteLine( DateTime.Now.Subtract(t));          
    }

OP想要获取上次关机的日期时间。上次重启时间不是同一个东西! - David

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接